SlideShare una empresa de Scribd logo
Formularios
Realizada por:
Christian Aquino |@cj_aquino
Diego Ramirez |@thedarsideofit
Gonzalo Alonso |@GonzaloAlonsoD
Diego Barros |@Inmzombie
Para: Hydras C&S |@hydras_cs
Basada en Libro Symfony 2 en español Nacho Pacheco y The Book
Formularios:
Los formularios son la manera de llevar los datos desde el client-side al server-side
<h1>Contacto...</h1>
<form action="/index.php" method="POST">
<input type="text" name="nombre" >
<br>
<input type="text" name="apellido" >
<br>
<input type="text" name="email" >
<br><input type="text" name="telefono" >
<br><textarea rows="5" name="comentario" >
</textarea><br>
<input type="submit" value="Enviar">
</form>
Utilizar formularios HTML es una de las más comunes —y desafiantes— tareas para un desarrollador
web. Symfony2 integra un componente Form que se ocupa de facilitarnos la utilización de formularios.
En este capítulo, vamos a poder construir un formulario complejo desde el principio, del cual, de paso,
aprenderemos las características más importantes de la biblioteca de formularios.
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$to = 'mail@ejemplo.com';
$subject = "Mensaje enviado desde www.ejemplo.com.ar";
$contenido .= "Nombre: ".$_POST["nombre"]."n";
$contenido .= "Apellido: ".$_POST["apellido"]."n";
$contenido .= "Teléfono: ".$_POST["telefono"]."nn";
$contenido .= "Email: ".$_POST["email"]."nn";
$contenido .= "Comentario: ".$_POST["comentario"]."nn";
$header = "From: contacto@ejemplo.comnn";
$header .= "Mime-Version: 1.0n";
$header .= "Content-Type: text/plain";
if(mail($to, $subject, $contenido ,$header)){
//...
...
?>
Creando un formulario sencillo
Vamos a hacer un ejemplo construyendo una sencilla aplicación de tareas pendientes que necesita
mostrar tus «pendientes». Debido a que tus usuarios tendrán que editar y crear tareas, debemos que
crear un formulario. Pero antes de empezar, vamos a concentrarnos en la clase genérica Task que
representa y almacena los datos para una sola tarea:
// src/Acme/TaskBundle/Entity/Task.php
namespace AcmeTaskBundleEntity;
class Task
{
protected $task;
protected $dueDate;
public function getTask($task) {
return $this->task;
}
public function setTask($task) {
return $this->task = $task;
}
public function getDueDate() {
return $this->dueDate;
}
public function setDueDate(DateTime $dueDate = null) {
$this->dueDate = $dueDate;
}
}
Esta clase es un «antiguo objeto PHP sencillo», ya que, hasta ahora, no tiene nada que ver con
Symfony o cualquier otra biblioteca. Es simplemente un objeto PHP normal que directamente
resuelve un problema dentro de tu aplicación (es decir, la necesidad de representar una tarea
pendiente en tu aplicación). Por supuesto, al final, vamos a poder enviar datos a una instancia de
Task (a través de un formulario), validar sus datos, y persistirla en una base de datos.
php app/console generate:bundle --
namespace=Acme/TaskBundle
Podemos crear el bundle para ir probando:
Construyendo el formulario
Ahora podemos crear y reproducir el formulario HTML real. En Symfony2, esto se hace construyendo
un objeto Form y luego pintándolo en una plantilla. Por ahora, esto se puede hacer en el interior de un
controlador:
// src/Acme/TaskBundle/Controller/DefaultController.php
namespace AcmeTaskBundleController;
use SymfonyBundleFrameworkBundleControllerController;
use AcmeTaskBundleEntityTask;
use SymfonyComponentHttpFoundationRequest;
class DefaultController extends Controller {
public function newAction(Request $request) {
// crea una task y le asigna algunos datos ficticios para este ejemplo
$task = new Task();
$task->setTask('Write a blog post');
$task->setDueDate(new DateTime('tomorrow'));
$form = $this->createFormBuilder($task)
->add('task', 'text')
->add('dueDate', 'date')
->getForm();
return $this->render('AcmeTaskBundle:Default:new.html.twig', array(
'form' => $form->createView(),
));
}
La creación de un formulario requiere relativamente poco código, porque los objetos form de
Symfony2 se construyen con un «generador de formularios». El propósito del generador de
formularios es permitirte escribir sencillas «recetas» de formulario, y hacer todo el trabajo pesado de
la construcción de un formulario.
En este ejemplo, añadiste dos campos al formulario —task y dueDate(fecha de vencimiento)— que
corresponden a las propiedades task y dueDate de la clase Task. También asignaste a cada uno un
«tipo» (por ejemplo, text, date), el cual entre otras cosas, determina qué etiqueta de formulario HTML
se dibuja para ese campo.
Symfony2 viene con muchos tipos integrados
Reproduciendo el formulario
Ahora que creamos el formulario, el siguiente paso es dibujarlo. Lo puedemos hacer pasando un
objeto view especial para formularios a tu plantilla (tengan en cuenta la declaración $form-
>createView() en el controlador de arriba) y usando un conjunto de funciones ayudantes de
formulario:
{# src/Acme/TaskBundle/Resources/views/Default/new.html.twig #}
<form action="{{ path('task_new') }}" method="post" {{ form_enctype(form) }}>
{{ form_widget(form) }}
<input type="submit" />
</form>
<!-- src/Acme/TaskBundle/Resources/views/Default/new.html.php -->
<form action="<?php echo $view['router']->generate('task_new') ?>" method="post" <?php echo $view['form']->enctype($form) ?>
>
<?php echo $view['form']->widget($form) ?>
<input type="submit" />
</form>
Al imprimir form_widget(form), se pinta cada campo en el formulario, junto con la etiqueta y un
mensaje de error (si lo hay). Tan fácil como esto, aunque no es muy flexible (todavía). Por lo general,
se querrá reproducir individualmente cada campo del formulario para que se pueda controlar la
apariencia del formulario.
Antes de continuar, observemos cómo el campo de entrada task reproducido tiene el valor de la
propiedad task del objeto $task (es decir, «Escribe una entrada del blog»). El primer trabajo de un
formulario es: tomar datos de un objeto y traducirlos a un formato idóneo para reproducirlos en un
formulario HTML.
Procesando el envío del formulario
El segundo trabajo de un formulario es traducir los datos enviados por el usuario a las propiedades de
un objeto. Para lograrlo, los datos presentados por el usuario deben estar vinculados al formulario.
Añade la siguiente funcionalidad a tu controlador:
// ...
public function newAction(Request $request) {
// sólo configura un objeto $task fresco (remueve los datos de prueba)
$task = new Task();
$form = $this->createFormBuilder($task)
->add('task', 'text')
->add('dueDate', 'date')
->getForm();
if ($request->isMethod('POST')) {
$form->bind($request);
if ($form->isValid()) {
// realiza alguna acción, tal como guardar la tarea en la base de datos
return $this->redirect($this->generateUrl('task_success'));
}
}
Tan pronto como se llame a bind(), los datos presentados se transfieren inmediatamente al objeto
subyacente. Esto ocurre independientemente de si los datos subyacentes son válidos realmente o no.
Este controlador sigue un patrón común para el manejo de formularios, y tiene tres posibles rutas:
1. Inicialmente, cuando se carga el formulario en un navegador, el método de la petición esGET, lo
cual significa simplemente que se debe crear y reproducir el formulario;
2. Cuando el usuario envía el formulario (es decir, el método es POST), pero los datos
presentados no son válidos (la validación se trata en la siguiente sección), el formulario es
vinculado y, a continuación reproducido, esta vez mostrando todos los errores de validación;
3. Cuando el usuario envía el formulario con datos válidos, el formulario es vinculado y en ese
momento tienes la oportunidad de realizar algunas acciones usando el objeto$task (por
ejemplo, persistirlo a la base de datos) antes de redirigir al usuario a otra página (por ejemplo,
una página de «agradecimiento» o «éxito»).
Validando formularios
En Symfony2, la validación se aplica al objeto subyacente (por ejemplo, Task). En otras palabras, la
cuestión no es si el «formulario» es válido, sino más bien si el objeto $task es válido después de
aplicarle los datos enviados en el formulario. Invocar a $form->isValid() es un atajo que pregunta al
objeto $task si tiene datos válidos o no.
La validación se realiza añadiendo un conjunto de reglas (llamadas restricciones) a una clase. Para
ver esto en acción, añade restricciones de validación para que el campo task no pueda estar vacío y
el campo dueDate no pueda estar vacío y debe ser un objeto DateTime válido.
# Acme/TaskBundle/Resources/config/validation.yml
AcmeTaskBundleEntityTask:
properties:
task:
- NotBlank: ~
dueDate:
- NotBlank: ~
- Type: DateTime
YAML
// Acme/TaskBundle/Entity/Task.php
use SymfonyComponentValidatorConstraints as Assert;
class Task {
/**
* @AssertNotBlank()
*/
public $task;
/**
* @AssertNotBlank()
* @AssertType("DateTime")
*/
protected $dueDate;
Annotations
Tipos de campo integrados
Symfony estándar viene con un gran grupo de tipos de campo que cubre todos los campos de
formulario comunes y tipos de datos necesarios:
Campos de texto
● text
● textarea
● email
● integer
● money
● number
● password
● percent
● search
● url
Campos de elección
● choice
● entity
● country
● language
● locale
● timezone
Campos de fecha y
hora
● date
● datetime
● time
● birthday
Otros campos
● checkbox
● file
● radio
Campos agrupados
● collection
● repeated
Campos ocultos
● hidden
● csrf
Campos base
● field
● form
Tipo de campo Form
Fijarse SymfonyComponentFormExtensionCoreTypeFormType.
El tipo form predefine un par de opciones que luego estarán disponibles en todos los campos.
data
tipo: mixed predeterminado: De manera predeterminada al campo del objeto subyacente (si existe)
required
tipo: Boolean predeterminado: true
constraints(limitaciones)
tipo: arreglo o SymfonyComponentValidatorConstraint predefinido: null
cascade_validation
tipo: Booleano predeterminado: false
disabled
type: boolean default: false
trim
tipo: Boolean predeterminado: true
mapped
tipo: boolean
attr
tipo: array predeterminado: Un arreglo vacío
translation_domain
tipo: string predefinido: messages —(mensajes)
Reproduciendo un formulario en una plantilla
Hasta ahora, has visto cómo se puede reproducir todo el formulario con una sola línea de código. Por
supuesto, generalmente necesitarás mucha más flexibilidad al reproducirlo:
{# src/Acme/TaskBundle/Resources/views/Default/new.html.twig #}
<form action="{{ path('task_new') }}" method="post" {{ form_enctype(form) }}>
{{ form_errors(form) }}
{{ form_row(form.task) }}
{{ form_row(form.dueDate) }}
{{ form_rest(form) }}
<input type="submit" />
</form>
Échale un vistazo a cada parte:
● form_enctype(form) — Si por lo menos un campo es para carga de archivos, se reproduce el obligado enctype="
multipart/form-data";
● form_errors(form) — Dibuja cualquier error global para todo el formulario (los errores específicos al campo se
muestran junto a cada campo);
● form_row(form.dueDate) — Dibuja la etiqueta, cualquier error, y el elemento gráficoHTML del formulario para el
campo en cuestión (por ejemplo, dueDate), por omisión, en el interior de un elemento div;
● form_rest(form) — Pinta todos los campos que aún no se han reproducido. Por lo general es buena idea realizar
una llamada a este ayudante en la parte inferior de cada formulario (en caso de haber olvidado sacar un campo o si
no quieres preocuparte de reproducir manualmente los campos ocultos). Este ayudante también es útil para tomar
Reproduciendo cada campo a mano
El ayudante form_row es magnífico porque rápidamente puedes reproducir cada campo del formulario
(y también puedes personalizar el formato utilizado para la «fila»). Pero, puesto que la vida no
siempre es tan simple, también puedes dibujar cada campo totalmente a mano. El producto final del
siguiente fragmento es el mismo que cuando usas el ayudante form_row:
{{ form_errors(form) }}
<div>
{{ form_label(form.task) }}
{{ form_errors(form.task) }}
{{ form_widget(form.task) }}
</div>
<div>
{{ form_label(form.dueDate) }}
{{ form_errors(form.dueDate) }}
{{ form_widget(form.dueDate) }}
</div>
{{ form_rest(form) }}
Twig
<?php echo $view['form']->errors($form) ?>
<div>
<?php echo $view['form']->label($form['task']) ?>
<?php echo $view['form']->errors($form['task']) ?>
<?php echo $view['form']->widget($form['task']) ?>
</div>
<div>
<?php echo $view['form']->label($form['dueDate']) ?>
<?php echo $view['form']->errors($form['dueDate']) ?>
<?php echo $view['form']->widget($form['dueDate']) ?>
</div>
<?php echo $view['form']->rest($form) ?>
PHP
Si la etiqueta generada automáticamente para un campo no es del todo correcta, la puedes
especificar explícitamente:
Twig
{{ form_label(form.task, 'Task Description') }}
<?php echo $view['form']->label($form['task'], 'Task Description') ?>
PHP
Algunos tipos de campo tienen opciones adicionales para su representación que puedes pasar al
elemento gráfico. Estas opciones están documentadas con cada tipo, pero una opción común es
attr, la cual te permite modificar los atributos en el elemento del formulario. Lo siguiente debería
añadir la clase task_field al campo de entrada de texto reproducido:
Twig
● {{ form_widget(form.task, { 'attr': {'class': 'task_field'} }) }}
PHP
● <?php echo $view['form']->widget($form['task'], array( 'attr' => array('class' => 'task_field'),)) ?>
Para recuperar el valor utilizado para el atributo nombre del campo en el formulario necesitas utilizar
el valor full_name:
Twig
{{ form.task.vars.full_name }}
PHP
<?php echo $form['task']->get('full_name') ?>
Creando clases Form
Como viste, puedes crear un formulario y utilizarlo directamente en un controlador. Sin embargo, una
mejor práctica es construir el formulario en una clase separada, independiente de las clases PHP,
misma que puedes reutilizar en cualquier lugar de tu aplicación. Podemos crear una nueva clase que
albergará la lógica para la construcción del formulario de la tarea:
// src/Acme/TaskBundle/Form/Type/TaskType.php
namespace AcmeTaskBundleFormType;
use SymfonyComponentFormAbstractType;
use SymfonyComponentFormFormBuilderInterface;
class TaskType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('task');
$builder->add('dueDate', null, array('widget' => 'single_text'));
}
public function getName()
{
return 'task';
}
}
Esta nueva clase contiene todas las indicaciones necesarias para crear el formulario de la tarea
(observar que el método getName() devolverá un identificador único para este «tipo» de formulario).
Lo puedes utilizar para construir rápidamente un objeto formulario en el controlador:
// src/Acme/TaskBundle/Controller/DefaultController.php
// agrega esta nueva declaración use en lo alto de la clase
use AcmeTaskBundleFormTypeTaskType;
public function newAction()
{
$task = ...;
$form = $this->createForm(new TaskType(), $task);
// ...
}
Configurando el data_class
Cada formulario tiene que conocer el nombre de la clase que contiene los datos subyacentes (por
ejemplo, AcmeTaskBundleEntityTask). Por lo general, esto sólo se deduce basándose en el objeto
pasado como segundo argumento de createForm(es decir, $task). Cuando comencemos a incorporar
formularios, esto ya no será suficiente. Así que, si bien no siempre es necesario, generalmente es
buena idea especificar directamente la opción data_class añadiendo lo siguiente al tipo de tu clase
formulario:
use SymfonyComponentOptionsResolverOptionsResolverInterface;
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AcmeTaskBundleEntityTask',
));
}
use SymfonyComponentFormFormBuilderInterface;
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('task');
$builder->add('dueDate', null, array('mapped' => false));
}
Además, si hay algunos campos en el formulario que no se incluyen en los datos presentados,
esos campos explícitamente se establecerán en null.
Los datos del campo se pueden acceder en un controlador con:
$form->get('dueDate')->getData();
Formularios y Doctrine
El objetivo de un formulario es traducir los datos de un objeto (por ejemplo, Task) a un formulario
HTML y luego traducir los datos enviados por el usuario al objeto original. Como tal, el tema de la
persistencia del objeto Task a la base de datos es del todo ajeno al tema de los formularios. Pero, si
has configurado la clase Task para persistirla a través de Doctrine (es decir, que le has añadido
metadatos de asignación), entonces persistirla después de la presentación de un formulario se puede
hacer cuando el formulario es válido:
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($task);
$em->flush();
return $this->redirect($this->generateUrl('task_success'));
}
Si por alguna razón, no tienes acceso a tu objeto $task original, lo puedes recuperar desde el formulario:
$task = $form->getData();
La clave es entender que cuando el formulario está vinculado, los datos presentados inmediatamente se
transfieren al objeto subyacente. Si deseas conservar los datos, sólo tendrás que conservar el objeto en
sí (el cual ya contiene los datos presentados).
Integrando formularios
A menudo, querrás crear un formulario que incluye campos de muchos objetos diferentes. Por
ejemplo, un formulario de registro puede contener datos que pertenecen a un objeto User, así como a
muchos objetos Address. Afortunadamente, esto es fácil y natural con el componente Form.
Integrando un solo objeto
Supongamos que cada Task pertenece a un simple objeto Categoría. Inicia, por supuesto, creando el
objeto Categoría:
// src/Acme/TaskBundle/Entity/Category.php
namespace AcmeTaskBundleEntity;
use SymfonyComponentValidatorConstraints as Assert;
class Category
{
/**
* @AssertNotBlank()
*/
public $name;
}
A continuación, añadiremos una nueva propiedad categoría a la clase Task:
// ...
class Task
{
// ...
/**
* @AssertType(type="AcmeTaskBundleEntityCategory")
*/
protected $category;
// ...
public function getCategory()
{
return $this->category;
}
public function setCategory(Category $category = null)
{
$this->category = $category;
}
}
// src/Acme/TaskBundle/Form/Type/CategoryType.php
namespace AcmeTaskBundleFormType;
use SymfonyComponentFormAbstractType;
use SymfonyComponentFormFormBuilderInterface;
use SymfonyComponentOptionsResolverOptionsResolverInterface;
class CategoryType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name');
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AcmeTaskBundleEntityCategory',
));
}
public function getName()
{
return 'category';
}
}
Ahora que actualizaste tu aplicación para reflejar las nuevas necesidades, crea una clase formulario
para que el usuario pueda modificar un objeto Categoría:
El objetivo final es permitir que la Categoría de una Task sea modificada justo dentro del mismo
formulario de la tarea. Para lograr esto, añade un campo categoría al objeto TaskType cuyo tipo es
una instancia de la nueva clase CategoryType:
use SymfonyComponentFormFormBuilderInterface;
public function buildForm(FormBuilderInterface $builder, array $options)
{
// ...
$builder->add('category', new CategoryType());
}
Los campos de CategoryType ahora se pueden reproducir junto a los de la clase TaskType. Para
activar la validación en CategoryType, añade la opción cascade_validation en TaskType:
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AcmeTaskBundleEntityTask',
'cascade_validation' => true,
));
}
Reproduce los campos de Categoría de la misma manera que los campos de la Taskoriginal:
{# ... #}
<h3>Category</h3>
<div class="category">
{{ form_row(form.category.name) }}
</div>
{{ form_rest(form) }}
{# ... #}
<!-- ... -->
<h3>Category</h3>
<div class="category">
<?php echo $view['form']->row($form['category']['name']) ?>
</div>
<?php echo $view['form']->rest($form) ?>
<!-- ... -->
Twig
PHP
Cuando el usuario envía el formulario, los datos presentados para los campos de Categoría se
utilizan para construir una instancia de Categoría, que entonces se establece en el campo categoría
de la instancia de la Tarea.
La instancia de Categoría es accesible naturalmente vía $task->getCategory() y la puedes persistir en
la base de datos o utilizarla como necesites.

Más contenido relacionado

La actualidad más candente

Programación orientada a objetos II
Programación orientada a objetos IIProgramación orientada a objetos II
Programación orientada a objetos II
yanburbano
 
Presentacion diseño web con jquery
Presentacion diseño web con jqueryPresentacion diseño web con jquery
Presentacion diseño web con jquery
Eutobar
 
Acceso a BBDD mediante un servlet
Acceso a BBDD mediante un servletAcceso a BBDD mediante un servlet
Acceso a BBDD mediante un servlet
jubacalo
 
Acciones JSP
Acciones JSPAcciones JSP
Acciones JSP
jubacalo
 
Jsp directiva page
Jsp directiva pageJsp directiva page
Jsp directiva page
jubacalo
 
Manual de jquery en pdf desarrollowebcom
Manual de jquery en pdf desarrollowebcomManual de jquery en pdf desarrollowebcom
Manual de jquery en pdf desarrollowebcom
jo_ram
 
Tema3[php]
Tema3[php]Tema3[php]
Tema3[php]
jhonjawer
 
Tema3
Tema3Tema3
Tema3
Magali Tc
 
Servlet Hola Mundo con Eclipse y Tomcat
Servlet Hola Mundo con Eclipse y TomcatServlet Hola Mundo con Eclipse y Tomcat
Servlet Hola Mundo con Eclipse y Tomcat
jubacalo
 
Clase 2 conceptos fundamentales
Clase 2   conceptos fundamentalesClase 2   conceptos fundamentales
Clase 2 conceptos fundamentales
hydras_cs
 
Conexión a postgres desde
Conexión a postgres desdeConexión a postgres desde
Conexión a postgres desde
jbersosa
 
Find File Servlet DB
Find File Servlet DBFind File Servlet DB
Find File Servlet DB
jubacalo
 
Web de noticias en Ajax
Web de noticias en AjaxWeb de noticias en Ajax
Web de noticias en Ajax
jubacalo
 
Programación III
Programación IIIProgramación III
Elementos de script en JSP
Elementos de script en JSPElementos de script en JSP
Elementos de script en JSP
jubacalo
 
Java servlets
Java servletsJava servlets
Java servlets
josevaldez20
 
Servlets y jsp
Servlets y jspServlets y jsp
Servlets y jsp
dtbadboy0
 
El Mal Odiado Javascript
El Mal Odiado JavascriptEl Mal Odiado Javascript
El Mal Odiado Javascript
El Jota
 
13. Configuracion De Aplicaciones Web Asp.Net
13.  Configuracion De Aplicaciones Web Asp.Net13.  Configuracion De Aplicaciones Web Asp.Net
13. Configuracion De Aplicaciones Web Asp.Net
guest3cf6ff
 
Jsp servlet- Tutorial BD Conexión
Jsp servlet- Tutorial BD ConexiónJsp servlet- Tutorial BD Conexión
Jsp servlet- Tutorial BD Conexión
Pattzy Montero
 

La actualidad más candente (20)

Programación orientada a objetos II
Programación orientada a objetos IIProgramación orientada a objetos II
Programación orientada a objetos II
 
Presentacion diseño web con jquery
Presentacion diseño web con jqueryPresentacion diseño web con jquery
Presentacion diseño web con jquery
 
Acceso a BBDD mediante un servlet
Acceso a BBDD mediante un servletAcceso a BBDD mediante un servlet
Acceso a BBDD mediante un servlet
 
Acciones JSP
Acciones JSPAcciones JSP
Acciones JSP
 
Jsp directiva page
Jsp directiva pageJsp directiva page
Jsp directiva page
 
Manual de jquery en pdf desarrollowebcom
Manual de jquery en pdf desarrollowebcomManual de jquery en pdf desarrollowebcom
Manual de jquery en pdf desarrollowebcom
 
Tema3[php]
Tema3[php]Tema3[php]
Tema3[php]
 
Tema3
Tema3Tema3
Tema3
 
Servlet Hola Mundo con Eclipse y Tomcat
Servlet Hola Mundo con Eclipse y TomcatServlet Hola Mundo con Eclipse y Tomcat
Servlet Hola Mundo con Eclipse y Tomcat
 
Clase 2 conceptos fundamentales
Clase 2   conceptos fundamentalesClase 2   conceptos fundamentales
Clase 2 conceptos fundamentales
 
Conexión a postgres desde
Conexión a postgres desdeConexión a postgres desde
Conexión a postgres desde
 
Find File Servlet DB
Find File Servlet DBFind File Servlet DB
Find File Servlet DB
 
Web de noticias en Ajax
Web de noticias en AjaxWeb de noticias en Ajax
Web de noticias en Ajax
 
Programación III
Programación IIIProgramación III
Programación III
 
Elementos de script en JSP
Elementos de script en JSPElementos de script en JSP
Elementos de script en JSP
 
Java servlets
Java servletsJava servlets
Java servlets
 
Servlets y jsp
Servlets y jspServlets y jsp
Servlets y jsp
 
El Mal Odiado Javascript
El Mal Odiado JavascriptEl Mal Odiado Javascript
El Mal Odiado Javascript
 
13. Configuracion De Aplicaciones Web Asp.Net
13.  Configuracion De Aplicaciones Web Asp.Net13.  Configuracion De Aplicaciones Web Asp.Net
13. Configuracion De Aplicaciones Web Asp.Net
 
Jsp servlet- Tutorial BD Conexión
Jsp servlet- Tutorial BD ConexiónJsp servlet- Tutorial BD Conexión
Jsp servlet- Tutorial BD Conexión
 

Similar a Clase 10 formularios

A toda máquina con herencia visual
A toda máquina con herencia visualA toda máquina con herencia visual
A toda máquina con herencia visual
Ignacio Monllor
 
Introducción al desarrollo Web: Frontend con Angular 6
Introducción al desarrollo Web: Frontend con Angular 6Introducción al desarrollo Web: Frontend con Angular 6
Introducción al desarrollo Web: Frontend con Angular 6
Gabriela Bosetti
 
06 validación
06 validación06 validación
06 validación
Roberto Moreno Doñoro
 
J M E R L I N P H P
J M E R L I N P H PJ M E R L I N P H P
J M E R L I N P H P
Mauro Gomez Mejia
 
Jquery para principianes
Jquery para principianesJquery para principianes
Jquery para principianes
Mauro Gomez Mejia
 
Ejercicio de automatizacion IntelliJ+reporte.docx
Ejercicio de automatizacion IntelliJ+reporte.docxEjercicio de automatizacion IntelliJ+reporte.docx
Ejercicio de automatizacion IntelliJ+reporte.docx
ssuser2e6b96
 
Php Bitter Sweet Symfony!
Php Bitter Sweet Symfony!Php Bitter Sweet Symfony!
Php Bitter Sweet Symfony!
Ricard Luquero
 
fonciones
foncionesfonciones
fonciones
devanito
 
Funciones
FuncionesFunciones
Funciones
Hector Ortiz
 
Dynamics crm-es
Dynamics crm-esDynamics crm-es
Dynamics crm-es
ansonjonel
 
Clase 5 controller
Clase 5 controllerClase 5 controller
Clase 5 controller
hydras_cs
 
Introducción a DJango
Introducción a DJangoIntroducción a DJango
Introducción a DJango
Luis Cruz Campos
 
TEMA Nº 4: GENERACIÓN DE CONTENIDO DINÁMICO CON JSP
TEMA Nº 4: GENERACIÓN DE CONTENIDO DINÁMICO CON JSPTEMA Nº 4: GENERACIÓN DE CONTENIDO DINÁMICO CON JSP
TEMA Nº 4: GENERACIÓN DE CONTENIDO DINÁMICO CON JSP
Anyeni Garay
 
Presentacion YII
Presentacion YIIPresentacion YII
Presentacion YII
Lenin Hernandez
 
Guiajs2
Guiajs2Guiajs2
Reportes En J Developer Parte 1 Y 2
Reportes En J Developer   Parte 1 Y 2Reportes En J Developer   Parte 1 Y 2
Reportes En J Developer Parte 1 Y 2
Steven Gomez
 
Directorio betabeers - symfony madrid
Directorio betabeers - symfony madridDirectorio betabeers - symfony madrid
Directorio betabeers - symfony madrid
betabeers
 
SALUDOS EN INGLES
SALUDOS EN INGLESSALUDOS EN INGLES
SALUDOS EN INGLES
ludiviarosa
 
Visual studio 2010
Visual studio 2010Visual studio 2010
Visual studio 2010
Daniel Olalde Soto
 
Introduccion mvc
Introduccion mvcIntroduccion mvc
Introduccion mvc
lissette_torrealba
 

Similar a Clase 10 formularios (20)

A toda máquina con herencia visual
A toda máquina con herencia visualA toda máquina con herencia visual
A toda máquina con herencia visual
 
Introducción al desarrollo Web: Frontend con Angular 6
Introducción al desarrollo Web: Frontend con Angular 6Introducción al desarrollo Web: Frontend con Angular 6
Introducción al desarrollo Web: Frontend con Angular 6
 
06 validación
06 validación06 validación
06 validación
 
J M E R L I N P H P
J M E R L I N P H PJ M E R L I N P H P
J M E R L I N P H P
 
Jquery para principianes
Jquery para principianesJquery para principianes
Jquery para principianes
 
Ejercicio de automatizacion IntelliJ+reporte.docx
Ejercicio de automatizacion IntelliJ+reporte.docxEjercicio de automatizacion IntelliJ+reporte.docx
Ejercicio de automatizacion IntelliJ+reporte.docx
 
Php Bitter Sweet Symfony!
Php Bitter Sweet Symfony!Php Bitter Sweet Symfony!
Php Bitter Sweet Symfony!
 
fonciones
foncionesfonciones
fonciones
 
Funciones
FuncionesFunciones
Funciones
 
Dynamics crm-es
Dynamics crm-esDynamics crm-es
Dynamics crm-es
 
Clase 5 controller
Clase 5 controllerClase 5 controller
Clase 5 controller
 
Introducción a DJango
Introducción a DJangoIntroducción a DJango
Introducción a DJango
 
TEMA Nº 4: GENERACIÓN DE CONTENIDO DINÁMICO CON JSP
TEMA Nº 4: GENERACIÓN DE CONTENIDO DINÁMICO CON JSPTEMA Nº 4: GENERACIÓN DE CONTENIDO DINÁMICO CON JSP
TEMA Nº 4: GENERACIÓN DE CONTENIDO DINÁMICO CON JSP
 
Presentacion YII
Presentacion YIIPresentacion YII
Presentacion YII
 
Guiajs2
Guiajs2Guiajs2
Guiajs2
 
Reportes En J Developer Parte 1 Y 2
Reportes En J Developer   Parte 1 Y 2Reportes En J Developer   Parte 1 Y 2
Reportes En J Developer Parte 1 Y 2
 
Directorio betabeers - symfony madrid
Directorio betabeers - symfony madridDirectorio betabeers - symfony madrid
Directorio betabeers - symfony madrid
 
SALUDOS EN INGLES
SALUDOS EN INGLESSALUDOS EN INGLES
SALUDOS EN INGLES
 
Visual studio 2010
Visual studio 2010Visual studio 2010
Visual studio 2010
 
Introduccion mvc
Introduccion mvcIntroduccion mvc
Introduccion mvc
 

Más de hydras_cs

Clase 15 FOS
Clase 15 FOSClase 15 FOS
Clase 15 FOS
hydras_cs
 
Clase 11 continuamos con formularios
Clase 11   continuamos con formulariosClase 11   continuamos con formularios
Clase 11 continuamos con formularios
hydras_cs
 
Clase 7 el modelo
Clase 7  el modeloClase 7  el modelo
Clase 7 el modelo
hydras_cs
 
Clase 6 twig
Clase 6 twigClase 6 twig
Clase 6 twig
hydras_cs
 
Clase 4 routing
Clase 4 routingClase 4 routing
Clase 4 routing
hydras_cs
 
Clase 3 instalación y primeros pasos
Clase 3 instalación y primeros pasosClase 3 instalación y primeros pasos
Clase 3 instalación y primeros pasos
hydras_cs
 
Sensio labsdesktop
Sensio labsdesktopSensio labsdesktop
Sensio labsdesktop
hydras_cs
 
Clase 1 introducción a symfony 2
Clase 1   introducción a symfony 2Clase 1   introducción a symfony 2
Clase 1 introducción a symfony 2
hydras_cs
 

Más de hydras_cs (8)

Clase 15 FOS
Clase 15 FOSClase 15 FOS
Clase 15 FOS
 
Clase 11 continuamos con formularios
Clase 11   continuamos con formulariosClase 11   continuamos con formularios
Clase 11 continuamos con formularios
 
Clase 7 el modelo
Clase 7  el modeloClase 7  el modelo
Clase 7 el modelo
 
Clase 6 twig
Clase 6 twigClase 6 twig
Clase 6 twig
 
Clase 4 routing
Clase 4 routingClase 4 routing
Clase 4 routing
 
Clase 3 instalación y primeros pasos
Clase 3 instalación y primeros pasosClase 3 instalación y primeros pasos
Clase 3 instalación y primeros pasos
 
Sensio labsdesktop
Sensio labsdesktopSensio labsdesktop
Sensio labsdesktop
 
Clase 1 introducción a symfony 2
Clase 1   introducción a symfony 2Clase 1   introducción a symfony 2
Clase 1 introducción a symfony 2
 

Clase 10 formularios

  • 1. Formularios Realizada por: Christian Aquino |@cj_aquino Diego Ramirez |@thedarsideofit Gonzalo Alonso |@GonzaloAlonsoD Diego Barros |@Inmzombie Para: Hydras C&S |@hydras_cs Basada en Libro Symfony 2 en español Nacho Pacheco y The Book
  • 2. Formularios: Los formularios son la manera de llevar los datos desde el client-side al server-side <h1>Contacto...</h1> <form action="/index.php" method="POST"> <input type="text" name="nombre" > <br> <input type="text" name="apellido" > <br> <input type="text" name="email" > <br><input type="text" name="telefono" > <br><textarea rows="5" name="comentario" > </textarea><br> <input type="submit" value="Enviar"> </form> Utilizar formularios HTML es una de las más comunes —y desafiantes— tareas para un desarrollador web. Symfony2 integra un componente Form que se ocupa de facilitarnos la utilización de formularios. En este capítulo, vamos a poder construir un formulario complejo desde el principio, del cual, de paso, aprenderemos las características más importantes de la biblioteca de formularios.
  • 3. <?php if ($_SERVER['REQUEST_METHOD'] === 'POST') { $to = 'mail@ejemplo.com'; $subject = "Mensaje enviado desde www.ejemplo.com.ar"; $contenido .= "Nombre: ".$_POST["nombre"]."n"; $contenido .= "Apellido: ".$_POST["apellido"]."n"; $contenido .= "Teléfono: ".$_POST["telefono"]."nn"; $contenido .= "Email: ".$_POST["email"]."nn"; $contenido .= "Comentario: ".$_POST["comentario"]."nn"; $header = "From: contacto@ejemplo.comnn"; $header .= "Mime-Version: 1.0n"; $header .= "Content-Type: text/plain"; if(mail($to, $subject, $contenido ,$header)){ //... ... ?>
  • 4. Creando un formulario sencillo Vamos a hacer un ejemplo construyendo una sencilla aplicación de tareas pendientes que necesita mostrar tus «pendientes». Debido a que tus usuarios tendrán que editar y crear tareas, debemos que crear un formulario. Pero antes de empezar, vamos a concentrarnos en la clase genérica Task que representa y almacena los datos para una sola tarea: // src/Acme/TaskBundle/Entity/Task.php namespace AcmeTaskBundleEntity; class Task { protected $task; protected $dueDate; public function getTask($task) { return $this->task; } public function setTask($task) { return $this->task = $task; } public function getDueDate() { return $this->dueDate; } public function setDueDate(DateTime $dueDate = null) { $this->dueDate = $dueDate; } }
  • 5. Esta clase es un «antiguo objeto PHP sencillo», ya que, hasta ahora, no tiene nada que ver con Symfony o cualquier otra biblioteca. Es simplemente un objeto PHP normal que directamente resuelve un problema dentro de tu aplicación (es decir, la necesidad de representar una tarea pendiente en tu aplicación). Por supuesto, al final, vamos a poder enviar datos a una instancia de Task (a través de un formulario), validar sus datos, y persistirla en una base de datos. php app/console generate:bundle -- namespace=Acme/TaskBundle Podemos crear el bundle para ir probando:
  • 6. Construyendo el formulario Ahora podemos crear y reproducir el formulario HTML real. En Symfony2, esto se hace construyendo un objeto Form y luego pintándolo en una plantilla. Por ahora, esto se puede hacer en el interior de un controlador: // src/Acme/TaskBundle/Controller/DefaultController.php namespace AcmeTaskBundleController; use SymfonyBundleFrameworkBundleControllerController; use AcmeTaskBundleEntityTask; use SymfonyComponentHttpFoundationRequest; class DefaultController extends Controller { public function newAction(Request $request) { // crea una task y le asigna algunos datos ficticios para este ejemplo $task = new Task(); $task->setTask('Write a blog post'); $task->setDueDate(new DateTime('tomorrow')); $form = $this->createFormBuilder($task) ->add('task', 'text') ->add('dueDate', 'date') ->getForm(); return $this->render('AcmeTaskBundle:Default:new.html.twig', array( 'form' => $form->createView(), )); }
  • 7. La creación de un formulario requiere relativamente poco código, porque los objetos form de Symfony2 se construyen con un «generador de formularios». El propósito del generador de formularios es permitirte escribir sencillas «recetas» de formulario, y hacer todo el trabajo pesado de la construcción de un formulario. En este ejemplo, añadiste dos campos al formulario —task y dueDate(fecha de vencimiento)— que corresponden a las propiedades task y dueDate de la clase Task. También asignaste a cada uno un «tipo» (por ejemplo, text, date), el cual entre otras cosas, determina qué etiqueta de formulario HTML se dibuja para ese campo. Symfony2 viene con muchos tipos integrados Reproduciendo el formulario Ahora que creamos el formulario, el siguiente paso es dibujarlo. Lo puedemos hacer pasando un objeto view especial para formularios a tu plantilla (tengan en cuenta la declaración $form- >createView() en el controlador de arriba) y usando un conjunto de funciones ayudantes de formulario: {# src/Acme/TaskBundle/Resources/views/Default/new.html.twig #} <form action="{{ path('task_new') }}" method="post" {{ form_enctype(form) }}> {{ form_widget(form) }} <input type="submit" /> </form> <!-- src/Acme/TaskBundle/Resources/views/Default/new.html.php --> <form action="<?php echo $view['router']->generate('task_new') ?>" method="post" <?php echo $view['form']->enctype($form) ?> > <?php echo $view['form']->widget($form) ?> <input type="submit" /> </form>
  • 8. Al imprimir form_widget(form), se pinta cada campo en el formulario, junto con la etiqueta y un mensaje de error (si lo hay). Tan fácil como esto, aunque no es muy flexible (todavía). Por lo general, se querrá reproducir individualmente cada campo del formulario para que se pueda controlar la apariencia del formulario. Antes de continuar, observemos cómo el campo de entrada task reproducido tiene el valor de la propiedad task del objeto $task (es decir, «Escribe una entrada del blog»). El primer trabajo de un formulario es: tomar datos de un objeto y traducirlos a un formato idóneo para reproducirlos en un formulario HTML. Procesando el envío del formulario El segundo trabajo de un formulario es traducir los datos enviados por el usuario a las propiedades de un objeto. Para lograrlo, los datos presentados por el usuario deben estar vinculados al formulario. Añade la siguiente funcionalidad a tu controlador: // ... public function newAction(Request $request) { // sólo configura un objeto $task fresco (remueve los datos de prueba) $task = new Task(); $form = $this->createFormBuilder($task) ->add('task', 'text') ->add('dueDate', 'date') ->getForm(); if ($request->isMethod('POST')) { $form->bind($request); if ($form->isValid()) { // realiza alguna acción, tal como guardar la tarea en la base de datos return $this->redirect($this->generateUrl('task_success')); } }
  • 9. Tan pronto como se llame a bind(), los datos presentados se transfieren inmediatamente al objeto subyacente. Esto ocurre independientemente de si los datos subyacentes son válidos realmente o no. Este controlador sigue un patrón común para el manejo de formularios, y tiene tres posibles rutas: 1. Inicialmente, cuando se carga el formulario en un navegador, el método de la petición esGET, lo cual significa simplemente que se debe crear y reproducir el formulario; 2. Cuando el usuario envía el formulario (es decir, el método es POST), pero los datos presentados no son válidos (la validación se trata en la siguiente sección), el formulario es vinculado y, a continuación reproducido, esta vez mostrando todos los errores de validación; 3. Cuando el usuario envía el formulario con datos válidos, el formulario es vinculado y en ese momento tienes la oportunidad de realizar algunas acciones usando el objeto$task (por ejemplo, persistirlo a la base de datos) antes de redirigir al usuario a otra página (por ejemplo, una página de «agradecimiento» o «éxito»).
  • 10. Validando formularios En Symfony2, la validación se aplica al objeto subyacente (por ejemplo, Task). En otras palabras, la cuestión no es si el «formulario» es válido, sino más bien si el objeto $task es válido después de aplicarle los datos enviados en el formulario. Invocar a $form->isValid() es un atajo que pregunta al objeto $task si tiene datos válidos o no. La validación se realiza añadiendo un conjunto de reglas (llamadas restricciones) a una clase. Para ver esto en acción, añade restricciones de validación para que el campo task no pueda estar vacío y el campo dueDate no pueda estar vacío y debe ser un objeto DateTime válido. # Acme/TaskBundle/Resources/config/validation.yml AcmeTaskBundleEntityTask: properties: task: - NotBlank: ~ dueDate: - NotBlank: ~ - Type: DateTime YAML
  • 11. // Acme/TaskBundle/Entity/Task.php use SymfonyComponentValidatorConstraints as Assert; class Task { /** * @AssertNotBlank() */ public $task; /** * @AssertNotBlank() * @AssertType("DateTime") */ protected $dueDate; Annotations
  • 12. Tipos de campo integrados Symfony estándar viene con un gran grupo de tipos de campo que cubre todos los campos de formulario comunes y tipos de datos necesarios: Campos de texto ● text ● textarea ● email ● integer ● money ● number ● password ● percent ● search ● url Campos de elección ● choice ● entity ● country ● language ● locale ● timezone Campos de fecha y hora ● date ● datetime ● time ● birthday Otros campos ● checkbox ● file ● radio Campos agrupados ● collection ● repeated Campos ocultos ● hidden ● csrf Campos base ● field ● form
  • 13. Tipo de campo Form Fijarse SymfonyComponentFormExtensionCoreTypeFormType. El tipo form predefine un par de opciones que luego estarán disponibles en todos los campos. data tipo: mixed predeterminado: De manera predeterminada al campo del objeto subyacente (si existe) required tipo: Boolean predeterminado: true constraints(limitaciones) tipo: arreglo o SymfonyComponentValidatorConstraint predefinido: null cascade_validation tipo: Booleano predeterminado: false disabled type: boolean default: false trim tipo: Boolean predeterminado: true mapped tipo: boolean attr tipo: array predeterminado: Un arreglo vacío translation_domain tipo: string predefinido: messages —(mensajes)
  • 14. Reproduciendo un formulario en una plantilla Hasta ahora, has visto cómo se puede reproducir todo el formulario con una sola línea de código. Por supuesto, generalmente necesitarás mucha más flexibilidad al reproducirlo: {# src/Acme/TaskBundle/Resources/views/Default/new.html.twig #} <form action="{{ path('task_new') }}" method="post" {{ form_enctype(form) }}> {{ form_errors(form) }} {{ form_row(form.task) }} {{ form_row(form.dueDate) }} {{ form_rest(form) }} <input type="submit" /> </form> Échale un vistazo a cada parte: ● form_enctype(form) — Si por lo menos un campo es para carga de archivos, se reproduce el obligado enctype=" multipart/form-data"; ● form_errors(form) — Dibuja cualquier error global para todo el formulario (los errores específicos al campo se muestran junto a cada campo); ● form_row(form.dueDate) — Dibuja la etiqueta, cualquier error, y el elemento gráficoHTML del formulario para el campo en cuestión (por ejemplo, dueDate), por omisión, en el interior de un elemento div; ● form_rest(form) — Pinta todos los campos que aún no se han reproducido. Por lo general es buena idea realizar una llamada a este ayudante en la parte inferior de cada formulario (en caso de haber olvidado sacar un campo o si no quieres preocuparte de reproducir manualmente los campos ocultos). Este ayudante también es útil para tomar
  • 15. Reproduciendo cada campo a mano El ayudante form_row es magnífico porque rápidamente puedes reproducir cada campo del formulario (y también puedes personalizar el formato utilizado para la «fila»). Pero, puesto que la vida no siempre es tan simple, también puedes dibujar cada campo totalmente a mano. El producto final del siguiente fragmento es el mismo que cuando usas el ayudante form_row: {{ form_errors(form) }} <div> {{ form_label(form.task) }} {{ form_errors(form.task) }} {{ form_widget(form.task) }} </div> <div> {{ form_label(form.dueDate) }} {{ form_errors(form.dueDate) }} {{ form_widget(form.dueDate) }} </div> {{ form_rest(form) }} Twig
  • 16. <?php echo $view['form']->errors($form) ?> <div> <?php echo $view['form']->label($form['task']) ?> <?php echo $view['form']->errors($form['task']) ?> <?php echo $view['form']->widget($form['task']) ?> </div> <div> <?php echo $view['form']->label($form['dueDate']) ?> <?php echo $view['form']->errors($form['dueDate']) ?> <?php echo $view['form']->widget($form['dueDate']) ?> </div> <?php echo $view['form']->rest($form) ?> PHP
  • 17. Si la etiqueta generada automáticamente para un campo no es del todo correcta, la puedes especificar explícitamente: Twig {{ form_label(form.task, 'Task Description') }} <?php echo $view['form']->label($form['task'], 'Task Description') ?> PHP Algunos tipos de campo tienen opciones adicionales para su representación que puedes pasar al elemento gráfico. Estas opciones están documentadas con cada tipo, pero una opción común es attr, la cual te permite modificar los atributos en el elemento del formulario. Lo siguiente debería añadir la clase task_field al campo de entrada de texto reproducido: Twig ● {{ form_widget(form.task, { 'attr': {'class': 'task_field'} }) }} PHP ● <?php echo $view['form']->widget($form['task'], array( 'attr' => array('class' => 'task_field'),)) ?>
  • 18. Para recuperar el valor utilizado para el atributo nombre del campo en el formulario necesitas utilizar el valor full_name: Twig {{ form.task.vars.full_name }} PHP <?php echo $form['task']->get('full_name') ?>
  • 19. Creando clases Form Como viste, puedes crear un formulario y utilizarlo directamente en un controlador. Sin embargo, una mejor práctica es construir el formulario en una clase separada, independiente de las clases PHP, misma que puedes reutilizar en cualquier lugar de tu aplicación. Podemos crear una nueva clase que albergará la lógica para la construcción del formulario de la tarea: // src/Acme/TaskBundle/Form/Type/TaskType.php namespace AcmeTaskBundleFormType; use SymfonyComponentFormAbstractType; use SymfonyComponentFormFormBuilderInterface; class TaskType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder->add('task'); $builder->add('dueDate', null, array('widget' => 'single_text')); } public function getName() { return 'task'; } }
  • 20. Esta nueva clase contiene todas las indicaciones necesarias para crear el formulario de la tarea (observar que el método getName() devolverá un identificador único para este «tipo» de formulario). Lo puedes utilizar para construir rápidamente un objeto formulario en el controlador: // src/Acme/TaskBundle/Controller/DefaultController.php // agrega esta nueva declaración use en lo alto de la clase use AcmeTaskBundleFormTypeTaskType; public function newAction() { $task = ...; $form = $this->createForm(new TaskType(), $task); // ... }
  • 21. Configurando el data_class Cada formulario tiene que conocer el nombre de la clase que contiene los datos subyacentes (por ejemplo, AcmeTaskBundleEntityTask). Por lo general, esto sólo se deduce basándose en el objeto pasado como segundo argumento de createForm(es decir, $task). Cuando comencemos a incorporar formularios, esto ya no será suficiente. Así que, si bien no siempre es necesario, generalmente es buena idea especificar directamente la opción data_class añadiendo lo siguiente al tipo de tu clase formulario: use SymfonyComponentOptionsResolverOptionsResolverInterface; public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => 'AcmeTaskBundleEntityTask', )); }
  • 22. use SymfonyComponentFormFormBuilderInterface; public function buildForm(FormBuilderInterface $builder, array $options) { $builder->add('task'); $builder->add('dueDate', null, array('mapped' => false)); } Además, si hay algunos campos en el formulario que no se incluyen en los datos presentados, esos campos explícitamente se establecerán en null. Los datos del campo se pueden acceder en un controlador con: $form->get('dueDate')->getData();
  • 23. Formularios y Doctrine El objetivo de un formulario es traducir los datos de un objeto (por ejemplo, Task) a un formulario HTML y luego traducir los datos enviados por el usuario al objeto original. Como tal, el tema de la persistencia del objeto Task a la base de datos es del todo ajeno al tema de los formularios. Pero, si has configurado la clase Task para persistirla a través de Doctrine (es decir, que le has añadido metadatos de asignación), entonces persistirla después de la presentación de un formulario se puede hacer cuando el formulario es válido: if ($form->isValid()) { $em = $this->getDoctrine()->getManager(); $em->persist($task); $em->flush(); return $this->redirect($this->generateUrl('task_success')); } Si por alguna razón, no tienes acceso a tu objeto $task original, lo puedes recuperar desde el formulario: $task = $form->getData(); La clave es entender que cuando el formulario está vinculado, los datos presentados inmediatamente se transfieren al objeto subyacente. Si deseas conservar los datos, sólo tendrás que conservar el objeto en sí (el cual ya contiene los datos presentados).
  • 24. Integrando formularios A menudo, querrás crear un formulario que incluye campos de muchos objetos diferentes. Por ejemplo, un formulario de registro puede contener datos que pertenecen a un objeto User, así como a muchos objetos Address. Afortunadamente, esto es fácil y natural con el componente Form. Integrando un solo objeto Supongamos que cada Task pertenece a un simple objeto Categoría. Inicia, por supuesto, creando el objeto Categoría: // src/Acme/TaskBundle/Entity/Category.php namespace AcmeTaskBundleEntity; use SymfonyComponentValidatorConstraints as Assert; class Category { /** * @AssertNotBlank() */ public $name; }
  • 25. A continuación, añadiremos una nueva propiedad categoría a la clase Task: // ... class Task { // ... /** * @AssertType(type="AcmeTaskBundleEntityCategory") */ protected $category; // ... public function getCategory() { return $this->category; } public function setCategory(Category $category = null) { $this->category = $category; } }
  • 26. // src/Acme/TaskBundle/Form/Type/CategoryType.php namespace AcmeTaskBundleFormType; use SymfonyComponentFormAbstractType; use SymfonyComponentFormFormBuilderInterface; use SymfonyComponentOptionsResolverOptionsResolverInterface; class CategoryType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder->add('name'); } public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => 'AcmeTaskBundleEntityCategory', )); } public function getName() { return 'category'; } } Ahora que actualizaste tu aplicación para reflejar las nuevas necesidades, crea una clase formulario para que el usuario pueda modificar un objeto Categoría:
  • 27. El objetivo final es permitir que la Categoría de una Task sea modificada justo dentro del mismo formulario de la tarea. Para lograr esto, añade un campo categoría al objeto TaskType cuyo tipo es una instancia de la nueva clase CategoryType: use SymfonyComponentFormFormBuilderInterface; public function buildForm(FormBuilderInterface $builder, array $options) { // ... $builder->add('category', new CategoryType()); } Los campos de CategoryType ahora se pueden reproducir junto a los de la clase TaskType. Para activar la validación en CategoryType, añade la opción cascade_validation en TaskType: public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => 'AcmeTaskBundleEntityTask', 'cascade_validation' => true, )); }
  • 28. Reproduce los campos de Categoría de la misma manera que los campos de la Taskoriginal: {# ... #} <h3>Category</h3> <div class="category"> {{ form_row(form.category.name) }} </div> {{ form_rest(form) }} {# ... #} <!-- ... --> <h3>Category</h3> <div class="category"> <?php echo $view['form']->row($form['category']['name']) ?> </div> <?php echo $view['form']->rest($form) ?> <!-- ... --> Twig PHP
  • 29. Cuando el usuario envía el formulario, los datos presentados para los campos de Categoría se utilizan para construir una instancia de Categoría, que entonces se establece en el campo categoría de la instancia de la Tarea. La instancia de Categoría es accesible naturalmente vía $task->getCategory() y la puedes persistir en la base de datos o utilizarla como necesites.