Uso de Data Transfer Objects (DTO) en formularios

Uno de los problemas que a veces nos encontramos en los formularios a menudo, es que necesitamos mostrar campos que no existen en nuestra entidad directamente ya que puede que necesitemos esos campos para construir un determinado objeto en funcion de las opciones que haya elegido.

En mi caso, tengo un formulario en el que aparecen 4 campos de tipo <select> y que son dependientes entre sí, y en funcion de las opciones el usuario tendra asignado unas cosas o otras, y 3 de estos campos no estan mapeados en la Entity.

Para ello, debemos hacer uso de los DTO (Data Transfer Object) que no son mas que “Objetos de Transferencia de Datos” o objetos “pasarela” para recoger la informacion del formulario y hacer a posteriori nuestras cosas.

Enctonces, imaginamos que tenemos una entidad Organizacion pero necesitamos 4 campos mas que no estan en nuestra entity pero que los necesitamos para el formulario:

<?php
namespace myApp\AppBundle\Model;

use Symfony\Component\Validator\Constraints as Assert;

class Enrol
{
    protected $organization;

    protected $plan;

    protected $edition;

    protected $group;

    /**
     * @Assert\NotBlank()
     */
    protected $roleUser;

    /**
     * Enrol constructor.
     */
    public function __construct()
    {
    }

    /**
     * @return mixed
     */
    public function getOrganization()
    {
        return $this->organization;
    }

    /**
     * @param mixed $organization
     */
    public function setOrganization($organization)
    {
        $this->organization = $organization;
    }

    /**
     * @return mixed
     */
    public function getPlan()
    {
        return $this->plan;
    }

    /**
     * @param mixed $plan
     */
    public function setPlan($plan)
    {
        $this->plan = $plan;
    }

    /**
     * @return mixed
     */
    public function getEdition()
    {
        return $this->edition;
    }

    /**
     * @param mixed $edition
     */
    public function setEdition($edition)
    {
        $this->edition = $edition;
    }

    /**
     * @return mixed
     */
    public function getGroup()
    {
        return $this->group;
    }

    /**
     * @param mixed $group
     */
    public function setGroup($group)
    {
        $this->group = $group;
    }

    /**
     * @return mixed
     */
    public function getRoleUser()
    {
        return $this->roleUser;
    }

    /**
     * @param mixed $roleUser
     */
    public function setRoleUser($roleUser)
    {
        $this->roleUser = $roleUser;
    }
}

Este es el modelo en el que se basara nuestro formulario para “hidratar” los campos del objeto que le pasemos.

Nuestro formulario quedaría así:

<?php

namespace myApp\AppBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

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' => 'myApp\AppBundle\Model\Enrol'
        ));
    }

    public function getName()
    {
        return 'myapp_bundle_enrol_type';
    }
}

Creamos el action:

/**
 * @Route("/organizations-form", name="org_form")
 */
public function orgFormAction(Request $request)
{
    $enrol = new Enrol();
    $form = $this->createForm(new EnrolType(), $enrol, array());
    $form->add('submit', 'submit');

    $form->handleRequest($request);
    if($form->isValid()){
        //Aqui harás lo que necesites con los datos del formulario
        //ya que tienes el DTO $enroll y con sus métodos puedes
        //recoger la informacion seleccionada en el formulario.
    }

    return $this->render('UserBundle::orgForm.html.twig', array(
        'form' => $form->createView()
    ));
}

Ya tenemos nuestro formulario, ahora la vista(puedes hacerla mas bonita si quieres):

{{ form_start(form) }}
{{ form_row(form.organization) }}
{{ form_row(form.plan) }}
{{ form_row(form.edition) }}
{{ form_row(form.group) }}
{{ form_row(form.roleUser) }}
{{ form_end(form) }}

Y con esto ya tendrias un formulario que no se a basado en una Entity y que contiene los campos que a ti te interesan y que despues procesaras en el Action de la forma que creas conveniente.

Espero que te haya servido, y si es asi, puedes compartir este articulo en redes sociales pulsando en ellas.

En otro articulo, explicare como hacer selects dependientes o anidados a traves de AJAX, otra de las necesidades que todo tenemos hoy en dia para los formularios. Pero eso sera en otro capitulo 🙂

Gracias y saludos a todos.

Anuncios

Un comentario en “Uso de Data Transfer Objects (DTO) en formularios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s