Este foro ya no está activo, así que no puedes publicar nuevas preguntas ni responder a las preguntas existentes.

'Setear' variables 'opcionales' en una clase de formulario de Symfony desde el controlador

25 de junio de 2015

Hola señor@s. Un saludo.

Tengo una duda. ¿Puedo pasarle a una clase form variables opcionales desde el controlador? La información que me suministran es la de pasar esta información al __constructor del formulario cuando se está instanciando. De la siguiente manera.

// controller
$form = $this->createForm(new MiLindoFormType($opcional), new MiLindaClase());
 
// ClassForm
class MiLindoForm extends AbstractType
{
    private $opcional;
 
    public function __construct($opcional = null)
    {
       $this->opcional = $opcional;
    }
 
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $opcional = $this->opcional;
 
        $builder
            ->add('ordenes', 'entity', array(
                'class' => 'AppBundle:Operaciones\OrdenesCompra',
                'property' => 'id_u_orden',
                'query_builder' => function(EntityRepository $er) use($opcional){
                    return $er->createQueryBuilder('co')
                    ->where('co.operaciones = :operacion')
                    ->setParameter('operacion', $opcional);
                },
            'empty_value' => 'Seleccione'
        ));
    }
 
}

De la anterior manera funciona. Mi duda es ¿cómo se puede hacer cuando tu formulario es un servicio?

$form = $this->createForm('my_lindo_form', new MiLindaClase(), array('opcion' => $opcional));

Saludos cordiales!


Respuestas

#1

Buenas, para lograr eso se utiliza el componente OptionsResolver de Symfony.

Donde los formularios poseen un método setDefaultOptions (configureOptions en Symfony 2.7), en ese método defines las opciones por defecto, las requeridas y los valores permitidos para esas opciones, por ejemplo:

<?php
 
namespace AppBundle\Form;
 
use AppBundle\Entity\Repository\CitaRepository;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;
 
class HoraCitaType extends AbstractType
{
    const FORMATO_HORA = 'h:i A';
 
    /**
     * @var CitaRepository
     */
    private $citasRepository;
 
    public function __construct($citasRepository)
    {
        $this->citasRepository = $citasRepository;
    }
 
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
       // Acá tengo las opciones disponibles en la variabe $options
 
        $builder->addEventSubscriber(new AddXXXListener(
            $this->citasRepository, 
            $options['fecha'],
            $options['hora_inicial'],
            $options['hora_hasta'],
            $options['clientes_por_hora'],
        ));
 
        //....
    }
 
    public function configureOptions(OptionsResolver $resolver)
    {
        // Aquí defino las opciones de configuración que mi formulario va a ofrecer
 
        $resolver->setRequired([
            'fecha',
            'clientes_por_hora',
        ]);
        $resolver->setAllowedTypes([
            'fecha' => ['string', 'Datetime', 'null'],
            'clientes_por_hora' => 'int',
        ]);
 
        $resolver->setNormalizer('fecha', function ($options, $fecha) {
            if (is_string($fecha)) {
                return \DateTime::createFromFormat('d/m/Y', $fecha);
            }
 
            return $fecha;
        });
 
        $resolver->setDefaults([
            'horas_desde' => '8:00 am',
            'horas_hasta' => '5:00 pm',
            'intervalo' => '+30 mins',
            'formato' => self::FORMATO_HORA,
        ]);
    }
 
    public function getName()
    {
        return 'hora_cita';
    }
}

Defino mi formulario como un servicio (Sea o no un servicio, las opciones de configuración se manejan igual):

services:
    app.horas_cita_type:
        class: AppBundle\Form\HoraCitaType
        arguments: [@app.citas_repository]
        tags:
            - { name: form.type, alias: hora_cita }

Luego en el controlador, le paso las opciones de configuración de la siguiente manera:

$form = $this->createForm('hora_cita', null, [
   'fecha' => new \Datetime(),
   'clientes_por_hora' => 3,
   'intervalo' => '+1 hours',
]);

Espero te sirva, saludos!

@manuel_j555

26 junio 2015, 13:27
#2

@manuel_j555 realmente me impresiona lo bien que manejas el componente de formularios. Yo soy incapaz de hacer nada avanzado con el :(

@javiereguiluz

26 junio 2015, 13:29
#3

En la empresa donde trabajo, la mayoría de formularios son bastante exigentes (eventos, campos opcionales dependientes, valores cargados en base a perfiles de usurio, etc), y nos ha tocado aprender a usar bien este componente :)

@manuel_j555

26 junio 2015, 13:36
#4

Muchas gracias. Sabía que se podía hacer. @Javier, y como decimos en mi tierra: la necesidad te lleva! :D

@cristian_angulo

26 junio 2015, 15:36