Nella lezione precedente abbiamo creato un form direttamente all’interno del controller, utilizzando lo schema:
class DefaultController extends Controller // estende la classe Controller di Symfony { ... public function newAction(Request $request) { ... // 1. creo i contenuti HTML del form $form = $this->createFormBuilder($task) ....
Il metodo ‘createFormBuilder()’ è utilizzato all’interno di ‘class DefaultController extends Controller’
Form come classe
Creare un form in una classe separata ci permette di riutilizzarlo più facilmente, lo schema di funzionanmento sarà
Il nostro controller invoca la classe contenente le istruzioni per creare il form: $form = $this->createForm(TaskType::class, $task);
public function newAction(Request $request) { ... // 1. creo i contenuti HTML del form // invia $task a TaskType.php classe TaskType $form = $this->createForm(TaskType::class, $task); ...
La Classe per creare il form TaskType.php:
... class TaskType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('task') ->add('dueDate', null, array('widget' => 'single_text')) ->add('save', SubmitType::class) ...
Il codice completo
src/AppBundle/Controller/DefaultController.php
<?php // src/AppBundle/Controller/DefaultController.php namespace AppBundle\Controller; use AppBundle\Entity\Task; // carica Task.php creato da me use AppBundle\Form\TaskType; // carica TaskType.php creato da me use Symfony\Component\HttpFoundation\Request; // capacità do renderizzare html render() use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;// NECESSARIO per utilizzare @Route use Symfony\Bundle\FrameworkBundle\Controller\Controller; // il bundle controller Symfony per usare createForm() class DefaultController extends Controller // deve estendere Controller { /** * @Route("/form") */ public function newAction(Request $request) { // creo il nuovo oggetto $task = new Task(); // die("interrompi qui"); // debug // 1. creo i contenuti HTML del form // invia $task a TaskType.php classe TaskType $form = $this->createForm(TaskType::class, $task); // 3. riconosce che il form non è stato inviato e non fa nulla $form->handleRequest($request); // 4. se il form è inviato AND valido if ($form->isSubmitted() && $form->isValid()) { // $form->getData() holds the submitted values // but, the original `$task` variable has also been updated $task = $form->getData();// ottieni i dati dal form // die ("interrompi qui 2"); // ... perform some action, such as saving the task to the database // for example, if Task is a Doctrine entity, save it! // $em = $this->getDoctrine()->getManager(); // $em->persist($task); // $em->flush(); // alla fine fai redirect all'esterno return $this->redirect('http://www.lucedigitale.com'); // oppure verso una @Route di Symfony //return $this->redirectToRoute('homepage'); } // 2. Il form viene creato e renderizzato return $this->render('default/new.html.twig', array( 'form' => $form->createView(), )); } }
src/AppBundle/Form/TaskType.php
<?php // src/AppBundle/Form/TaskType.php namespace AppBundle\Form; use Symfony\Component\Form\AbstractType; // form astratto use Symfony\Component\Form\FormBuilderInterface; // buildForm() use Symfony\Component\Form\Extension\Core\Type\SubmitType; // SubmitType::class class TaskType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('task') ->add('dueDate', null, array('widget' => 'single_text')) ->add('save', SubmitType::class) ; } }
src/AppBundle/Entity/Task.php
<?php // src/AppBundle/Entity/Task.php namespace AppBundle\Entity; use Symfony\Component\Validator\Constraints as Assert; // serve per @Assert\... class Task // dichiarazione esplicita dell'oggetto { /** * @Assert\NotBlank() * @Assert\EqualTo("Andrea") */ public $task; // cose da fare /** * @Assert\NotBlank() * @Assert\Type("\DateTime") */ protected $dueDate; // scadenza // NB metodi get e set obbligatori per permettere a 'Form component' di symfony di funzionare correttamente public function getTask() // ottieni le cose da fare { return $this->task; // assegna il valore che proviene dall'istanza $this-> } public function setTask($task) // setta le cose gda fare { $this->task = $task; } public function getDueDate() // ottieni la scadenza { return $this->dueDate; } public function setDueDate(\DateTime $dueDate = null) // setta la scadenza { $this->dueDate = $dueDate; } }
app/Resources/views/default/new.html.twig
{# app/Resources/views/default/new.html.twig #} {{ form_start(form) }} {{ form_widget(form) }} {{ form_end(form) }}
Come funziona?
0. al primo caricamento viene creato l’oggetto che contiene le mie variabili
$task = new Task();
1.
vengono creati i tag HTML per il form
$form = $this->createForm(TaskType::class, $task); -> punta alla Classe TaskType.php
Viene renderizzato il form render(‘default/new.html.twig’…
2. il metodo $form->handleRequest($request); rileva che il form non è stato inviato e non fa nulla
3. quando premo ‘submit’
– $form->handleRequest($request); ritorna TRUE
– i dati vengono salvati in $form e aggiornati in $task
a)
– $form viene controllato
– se non sono validi && $form->isValid()) { -> in realtà è una scorciatoia che significa $task->isValid())
– viene automaticamente renderizzata di nuovo la pagina con gli errori di validazione
b)
– $form viene controllato
– se sono validi && $form->isValid()) {
– viene inviata la richiesta POST alla pagina di provenieneza
– interrompe lo script con return facendo un redirect ad un’altra pagina, ad esempio di ringraziamento
NB: il redirect non darà la possibilità all’utente di fare “Refresh nel browser ed inviare di nuovo il form
Bibliografia:
symfony.com/doc/current/forms.html – Creating Form Classes