Symfony 2嵌入式表格集合多对多 [英] Symfony 2 Embedded Form Collection Many to Many
问题描述
我正在尝试通过添加一个集合来创建一个用户编辑表单,我想通过从下拉列表中选择它添加一个新的角色(仅限于DB中已经有的)
UserType.php:
类UserType extends AbstractType
{
public function buildForm(FormBuilderInterface $ builder,array $ options)
{
$ builder
- > add('username')
- > add('email')
- > add('forename')
- > add('surname')
- > add('isActive')
- > add('joinDate','date',array('input'=>'datetime','format '=''dd-MM-yyyy'))
- > add('lastActive','date',array('input'=>'datetime','format'=>'dd -MM-yyyy'))
- > add('groups', 'collection',array(
'type'=> new GroupType(),
'allow_add'=>真,
))
;
}
public function setDefaultOptions(OptionsResolverInterface $ resolver)
{
$ resolver-> setDefaults(array(
'data_class'=> Sfox\CoreBundle\Entity\User'
));
}
}
和GroupType.php:
class GroupType extends AbstractType
{
public function buildForm(FormBuilderInterface $ builder,array $ options)
{
$ builder
- > add('name')
- > add('role');
}
public function setDefaultOptions(OptionsResolverInterface $ resolver)
{
$ resolver-> setDefaults(array(
data_class=> Sfox\CoreBundle\Entity\Group'
));
}
}
在基本文本框中显示窗体中的角色,但是如果我在表单中添加一个条目,它会级联将一个新的条目保存到组中,如果我要编辑一个条目,它将更改基本的组数据。
我试图做一个GroupSelectType.php:
class GroupSelectType extends AbstractType
{
public function buildForm (FormBuilderInterface $ builder,array $ options)
{
$ builder
- > add('role','entity',array('class'=>'SfoxCoreBundle:Group' ,'property'=>'name'));
}
public function setDefaultOptions(OptionsResolverInterface $ resolver)
{
$ resolver-> setDefaults(array(
data_class=> Sfox\CoreBundle\Entity\Group'
));
}
}
将该字段添加为实体类型,显示正确的选择框(但使用默认值)我似乎无法将其绑定到UserType表单!
所有我想要的形式是修改底层的组用户实体中的ArrayCollection。
有谁知道如何实现这一点?
我为其他任何困扰类似问题的人制定了一个解决方案...
我不得不创建一个自定义表单类型,并将其声明为一个服务,以便我可以传入实体经理。然后我需要使一个dataTransformer将组对象更改为整数形式
自定义GroupSelectType:
class GroupSelectType extends AbstractType
{
/ **
* @var ObjectManager
* /
private $ OM;
private $ choices;
/ **
* @param ObjectManager $ om
* /
public function __construct(ObjectManager $ om)
{
$ this - > om = $ om;
//从数据库中构建我们的选择数组
$ groups = $ om-> getRepository('SfoxCoreBundle:Group') - > findAll();
foreach($ groups as $ group)
{
// choices [key] = label
$ this-> choices [$ group-> getId()] = $ group-> getName()。 [。 $ group-> getRole()。];
}
}
public function buildForm(FormBuilderInterface $ builder,array $ options)
{
$ transformer = new GroupToNumberTransformer($ this-> OM);
$ builder-> addModelTransformer($ transformer);
}
public function setDefaultOptions(OptionsResolverInterface $ resolver)
{
$ resolver-> setDefaults(array(
choices=> $这个选择,
));
}
public function getParent()
{
return'choice';
}
public function getName()
{
return'group_select';
}
}
在构造函数中,我得到所有可用的组和将它们放入一个选择数组,作为选项传递给选择框。
您还会注意到我正在使用自定义数据变换器,这是将groupId(在表单的呈现中使用)更改为组实体。我也将GroupSelectType作为一项服务,并在[@ doctrine.orm.entity_manager]中传递
services.yml(bundle config):
服务:
sfox_core.type.group_select:
类:Sfox\CoreBundle\Form\Type\GroupSelectType
参数:[@ doctrine.orm.entity_manager]
标签:
- {name:form.type,别名:group_select}
GroupToNumberTranformer.php
class GroupToNumberTransformer实现DataTransformerInterface
{
/ **
* @var ObjectManager
* /
private $ om;
/ **
* @param ObjectManager $ om
* /
public function __construct(ObjectManager $ om)
{
$ this - > om = $ om;
}
/ **
*将对象(组)转换为字符串(数字)。
*
* @param Group | null $ group
* @return string
* /
public function transform($ group)
{
if(null === $ group){
return;
}
return $ group-> getId();
}
/ **
*将字符串(数字)转换为对象(组)。
*
* @param string $ number
* @return Group | null
* @throws TransformationFailedException如果没有找到对象(组)。
* /
public function reverseTransform($ number)
{
if(!$ number){
return null;
}
$ group = $ this-> om
- > getRepository('SfoxCoreBundle:Group')
- > findOneBy(array '=> $ number))
;
if(null === $ group){
throw new TransformationFailedException(sprintf(
'具有ID%s的组不存在!',
$ number
));
}
return $ group;
}
}
我的修改后的UserType.php - 注意我使用我的自定义表单类型group_select现在作为一项服务运行:
class UserType extends AbstractType
{
private $ entityManager;
public function __construct($ entityManager)
{
$ this-> entityManager = $ entityManager;
public function buildForm(FormBuilderInterface $ builder,array $ options)
{
$ transformer = new GroupToNumberTransformer($ this-> entityManager);
$ builder
- > add('username')
- > add('email')
- > add('forename' b $ b - > add('surname')
- > add('isActive')
- > add('joinDate','date',array('input'=> 'datetime','format'=>'dd-MM-yyyy'))
- > add('lastActive','date',array('input'=>'datetime','format '=>'dd-MM-yyyy'));
$ builder
- > add(
$ builder-> create('groups','collection',array(
'type'=>'group_select'
'allow_add'=> true,
'options'=>数组(
'multiple'=> false,
'展开'=>假,
)
))
);
}
public function setDefaultOptions(OptionsResolverInterface $ resolver)
{
$ resolver-> setDefaults(array(
'data_class'=> Sfox\CoreBundle\Entity\User'
));
}
public function getName()
{
return'sfox_corebundle_usertype';
}
}
I have 2 Entities - User and Group. They have a many-to-many relationship and Group is used to store a users' roles.
I'm trying to make a User edit form by adding a collection, I want to be able to add a new role by selecting it from a dropdown (limited to what's already in the DB)
UserType.php:
class UserType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('username')
->add('email')
->add('forename')
->add('surname')
->add('isActive')
->add('joinDate', 'date', array('input' => 'datetime', 'format' => 'dd-MM-yyyy'))
->add('lastActive', 'date', array('input' => 'datetime', 'format' => 'dd-MM-yyyy'))
->add('groups', 'collection', array(
'type' => new GroupType(),
'allow_add' => true,
))
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Sfox\CoreBundle\Entity\User'
));
}
}
and GroupType.php:
class GroupType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('role');
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
"data_class" => 'Sfox\CoreBundle\Entity\Group'
));
}
}
This displays the roles in the form in basic text boxes, but if I add an entry to the form, it will cascade persist a new entry into Groups and if I were to edit an entry, it would change the underlying Group data.
I tried making a GroupSelectType.php:
class GroupSelectType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('role', 'entity', array('class'=>'SfoxCoreBundle:Group', 'property'=>'name'));
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
"data_class" => 'Sfox\CoreBundle\Entity\Group'
));
}
}
Adding the field as an "entity" type, this displays the correct select box (but with the default values) I cant seem to bind it to the UserType form!
All I want the form to do is modify the underlying 'groups' ArrayCollection in the User entity.
Does anyone know how I can achieve this?
Well I worked out a solution for anyone else struggling with similar problems...
I had to create a custom form type and declare it as a service so I could pass in the Entity Manager. I then needed to make a dataTransformer to change my group objects into an integer for the form
Custom GroupSelectType:
class GroupSelectType extends AbstractType
{
/**
* @var ObjectManager
*/
private $om;
private $choices;
/**
* @param ObjectManager $om
*/
public function __construct(ObjectManager $om)
{
$this->om = $om;
// Build our choices array from the database
$groups = $om->getRepository('SfoxCoreBundle:Group')->findAll();
foreach ($groups as $group)
{
// choices[key] = label
$this->choices[$group->getId()] = $group->getName() . " [". $group->getRole() ."]";
}
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$transformer = new GroupToNumberTransformer($this->om);
$builder->addModelTransformer($transformer);
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
"choices" => $this->choices,
));
}
public function getParent()
{
return 'choice';
}
public function getName()
{
return 'group_select';
}
}
In the constructor I'm getting all available groups and putting them into a "choices" array which is passed to the select box as an option.
You'll also notice I'm using a custom data transformer, this is to change the groupId (which is used in the rendering of the form) to a Group entity. I made the GroupSelectType a service as well and passed in the [@doctrine.orm.entity_manager]
services.yml (bundle config):
services:
sfox_core.type.group_select:
class: Sfox\CoreBundle\Form\Type\GroupSelectType
arguments: [@doctrine.orm.entity_manager]
tags:
- { name: form.type, alias: group_select }
GroupToNumberTranformer.php
class GroupToNumberTransformer implements DataTransformerInterface
{
/**
* @var ObjectManager
*/
private $om;
/**
* @param ObjectManager $om
*/
public function __construct(ObjectManager $om)
{
$this->om = $om;
}
/**
* Transforms an object (group) to a string (number).
*
* @param Group|null $group
* @return string
*/
public function transform($group)
{
if (null === $group) {
return "";
}
return $group->getId();
}
/**
* Transforms a string (number) to an object (group).
*
* @param string $number
* @return Group|null
* @throws TransformationFailedException if object (group) is not found.
*/
public function reverseTransform($number)
{
if (!$number) {
return null;
}
$group = $this->om
->getRepository('SfoxCoreBundle:Group')
->findOneBy(array('id' => $number))
;
if (null === $group) {
throw new TransformationFailedException(sprintf(
'Group with ID "%s" does not exist!',
$number
));
}
return $group;
}
}
And my modified UserType.php - Notice I'm using my custom form type "group_select" now as it's running as a service:
class UserType extends AbstractType
{
private $entityManager;
public function __construct($entityManager)
{
$this->entityManager = $entityManager;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$transformer = new GroupToNumberTransformer($this->entityManager);
$builder
->add('username')
->add('email')
->add('forename')
->add('surname')
->add('isActive')
->add('joinDate', 'date', array('input' => 'datetime', 'format' => 'dd-MM-yyyy'))
->add('lastActive', 'date', array('input' => 'datetime', 'format' => 'dd-MM-yyyy'));
$builder
->add(
$builder->create('groups', 'collection', array(
'type' => 'group_select',
'allow_add' => true,
'options' => array(
'multiple' => false,
'expanded' => false,
)
))
);
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Sfox\CoreBundle\Entity\User'
));
}
public function getName()
{
return 'sfox_corebundle_usertype';
}
}
这篇关于Symfony 2嵌入式表格集合多对多的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!