php - entitytype - symfony form collection bundle
Symfony 2 Embedded Form Collection Muchos a muchos (1)
Bueno, encontré una solución para cualquier otra persona que tenga problemas similares ...
Tuve que crear un tipo de formulario personalizado y declararlo como un servicio para poder pasar el Administrador de Entidades. Luego tuve que hacer un DataTransformer para cambiar los objetos de mi grupo en un entero para el formulario
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'';
}
}
En el constructor obtengo todos los grupos disponibles y los pongo en una matriz de "opciones" que se pasa al cuadro de selección como una opción.
También notará que estoy usando un transformador de datos personalizado, esto es para cambiar groupId (que se usa en la representación del formulario) a una entidad de grupo. También hice que GroupSelectType fuera un servicio y pasé en [@ 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;
}
}
Y mi UserType.php modificado: observe que estoy usando mi formulario personalizado tipo "group_select" ahora mientras se está ejecutando como un servicio:
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'';
}
}
Tengo 2 entidades: usuario y grupo. Tienen una relación de muchos a muchos y Group se usa para almacenar los roles de los usuarios.
Intento crear un formulario de edición de usuario agregando una colección, quiero poder agregar un nuevo rol seleccionándolo de un menú desplegable (limitado a lo que ya está en el 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''
));
}
}
y 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''
));
}
}
Esto muestra los roles en el formulario en cuadros de texto básicos, pero si agrego una entrada al formulario, continuará en cascada una nueva entrada en Grupos y si tuviera que editar una entrada, cambiaría los datos del Grupo subyacente.
Intenté hacer un 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''
));
}
}
Agregando el campo como un tipo de "entidad", esto muestra el cuadro de selección correcto (pero con los valores predeterminados) ¡Parece que no puedo vincularlo al formulario UserType!
Todo lo que quiero que haga la forma es modificar los ''grupos'' subyacentes ArrayCollection en la entidad Usuario.
¿Alguien sabe cómo puedo lograr esto?