Actualmente tengo una entidad User que puede ser matriculado(Enrol) a una Organization, o a un Group de una Edition. Para empezar no tengo una relacion directa entre User y Organization o Group, sino que hay otras entidades de por medio, por lo que estos campos en el formulario deben estar SIN mapear (mapped = false).
Ademas, un usuario puede tener mas de 1 Role por lo que tiene que haber una coleccion en dicho formulario.
Esto significa que, tengo un formulario embebido dentro del formulario de User, para poder añadir varios roles.
He creado un DTO(data transfer object) para agrupar los campos relacionados con la creacion del Role que son:
namespace AppBundle\Model;
class Enrol
{
protected $organization;
protected $plan;
protected $edition;
protected $group;
/**
* @Assert\NotBlank()
*/
protected $roleUser;
//CON SUS GETTERS Y SETTERS
}
Y el formulario que usa este DTO es asi:
class EnrolType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('organization', 'entity', array(
'label' => 'Seleccionar una Organización',
'class' => 'AppBundle:Organization',
'required' => false
))
->add('plan', 'entity', array(
'label' => 'Seleccionar un Plan',
'class' => 'AppBundle:Plan',
'required' => false
))
->add('edition', 'entity', array(
'label' => 'Seleccionar una Edición',
'class' => 'AppBundle:Edition',
'required' => false
))
->add('group', 'entity', array(
'label' => 'Seleccionar un Grupo',
'class' => 'AppBundle:Group',
'required' => false
))
->add('roleUser', 'entity', array(
'label' => 'Seleccionar un Rol',
'class' => 'AppBundle:Role',
'required' => false
));
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'efor\AppBundle\Model\Enrol'
));
}
public function getName()
{
return 'app_bundle_enrol_type';
}
}
Como podreis observar el formulario tiene 5 selects que son dependientes entre sí y que esto lo he solucionado usando AJAX para rellenar cada uno en funcion de lo que se a elegido.
Por otra parte, este formulario debe ir embebido en el formulario del registro de usuarios, como una coleccion pues puedo asignar a un ususario varios roles.
Para ello, y como en la entidad User no tengo dichos campos mapeados, he tenido que crear un DTO que representa a la entidad User pero que ademas añade la coleccion de Enrol y queda tal que asi:
namespace UserBundle\Model;
class User
{
//...
//Campos no relevantes
protected $enrol;
/**
* User constructor.
*/
public function __construct()
{
$this->enrol = new ArrayCollection();
}
/**
* @return mixed
*/
public function getEnrol()
{
return $this->enrol;
}
/**
* @param Enrol $enrol
*
* @return $this
*/
public function addEnrol(Enrol $enrol)
{
$this->enrol[] = $enrol;
return $this;
}
/**
* @param Enrol $enrol
*/
public function removeUser(Enrol $enrol)
{
$this->enrol->removeElement($enrol);
}
}
Con esto, ya tendria el modelo que hidrata el formulario, asi que el formulario quedaria asi:
class UserType extends AbstractType
{
/** @var ObjectManager $manager */
private $manager;
/**
* UserType constructor.
*
* @param ObjectManager $manager
*/
public function __construct(ObjectManager $manager)
{
$this->manager = $manager;
}
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add(//CAMPOS NO RELEVANTES)
->add('enrol', 'collection', array(
'type' => new EnrolType(),
'allow_add' => true,
'by_reference' => false,
'mapped' => false
));
}
/**
* @param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'UserBundle\Model\User'
));
}
/**
* @return string
*/
public function getName()
{
return 'user_bundle_User';
}
Ahora páso a crear el formulario en el Action del Controller tal que asi y se lo paso a la vista:
$userModel = new UserBundle\Model\User();
$userModel->addEnrol(new Enrol());
$createUserForm = $this->createForm(new UserType(), $userModel);
Aqui viene el problema y es que en la vista no me aparece el formulario embebido, aunque lo pinte como lo pinte ya que me dice que la coleccion es CERO.
{{ form_widget(form.enrol) }} {# PINTO TODO EL FORMULARIO ENTERO #}
{{ form.enrol | length }} {# ESTO ME DEVUELVE CERO #}
{# ESTO PINTARIA UN CAMPO DEL FORMULARIO EMBEBIDO, PERO NO PINTA NADA #}
<ul>
{% for enrol in form.enrol %}
<li>{{ form_widget(enrol.organization) }}</li>
{% endfor %}</ul>
Entonces, llegado a este punto no se muy bien que es lo que estoy haciendo mal, o que me he dejado por el camino, ya que pienso que es correcto.
Alguien que sepa que esta pasando, o que solucion me puede ofrecer para pintar esa coleccion de campos y que se permita añadir?
He seguido la receta para formularios embebidos como pone en la documentacion de Sf pero estoy atascado en este punto.
Gracias de antemano y perdon por la chapa ¡¡
Saludos ¡
Si lo resuelvo, colgare en mi blog la solucion para que el resto lo puedan leer y aprender tambien.