php

Symfony – Databases and the Doctrine ORM

Symfony non integra al suo interno componenti per lavorare con i databases, ma è integrato con la libreria di terze party ‘Doctrine’.
Possiamo trovare le librerie in Sources Files/vendor/doctrine

1. Aprire app/config/parameters.yml, questi sono i dati di accesso al DB, sono stati creati in fase di creazione del progetto


# app/config/parameters.yml

parameters:
    database_host:      localhost
    database_name:      test_project
    database_user:      root
    database_password:  

2. Aprire app/config/config.yml, qui settiamo i parametri per la corretta scrittura e charset che DEVE essere utf8mb4
utf8mb4 è stata introdotta dalla versione 5.5.3
Il vecchio utf8 usa al massimo 3 bytes, utf8mb4 usa al massimo 4 bytes per carattere, supportando quindi un maggior numero di caratteri.


doctrine:
    dbal:
        ...
        charset: utf8mb4
        default_table_options:
            charset: utf8mb4
            collate: utf8mb4_unicode_ci

3. Creiamo il DB da phpMyAdmin

Name: test_project
Codifica caratteri: utf8mb4_bin

4. Creiamola tabella: product
– Id integer auto increment
– name char lenght=100
– price decimal scale=2 (10,2)
– description text

NB: phpMyAdmin a volte non imposta correttamente 10,2 convertendolo in automatico in 10,0, in questo caso selezionare il tab SQL e digitale


ALTER TABLE `product` CHANGE `price` `price` DECIMAL(10,2) NOT NULL;

5. src/AppBundle/Entity/Product.php


<?php

// src/AppBundle/Entity/Product.php
namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="product")
 */
class Product
{
    
    // -------------------------------------------------------------------------    
    // Proprietà ---------------------------------------------------------------
    // -------------------------------------------------------------------------
    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=100)
     */
    private $name;

    /**
     * @ORM\Column(type="decimal", scale=2)
     */
    private $price;

    /**
     * @ORM\Column(type="text")
     */
    private $description;
    
    // -------------------------------------------------------------------------
    // Metodi ------------------------------------------------------------------
    // -------------------------------------------------------------------------
    public function getId() // ottieni
    {
        return $this->id; // assegna il valore che proviene dall'istanza $this->
    }
 
    public function setId($id) // setta
    {
        $this->id = $id;
    }
    // -------------------------------------------------------------------------
    public function getName() // ottieni
    {
        return $this->name; // assegna il valore che proviene dall'istanza $this->
    }
 
    public function setName($name) // setta
    {
        $this->name = $name;
    }
    // -------------------------------------------------------------------------
    public function getPrice() // ottieni
    {
        return $this->price; // assegna il valore che proviene dall'istanza $this->
    }
 
    public function setPrice($price) // setta
    {
        $this->price = $price;
    }
    // -------------------------------------------------------------------------
    public function getDescription() // ottieni
    {
        return $this->description; // assegna il valore che proviene dall'istanza $this->
    }
 
    public function setDescription($description) // setta
    {
        $this->description = $description;
    }
}// end class Product

Notare che nel creare l’oggetto aggiungo le specifiche per il salvaggio nel DB con la notazione /**


use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="product")
 */

6. src/AppBundle/Controller/SaveProduct.php


<?php

// src/AppBundle/Controller/SaveProduct.php
namespace AppBundle\Controller;

use AppBundle\Entity\Product;// Product.php che ho creato io
use Symfony\Bundle\FrameworkBundle\Controller\Controller; // il bundle controller Symfont
use Symfony\Component\HttpFoundation\Response; // namespace di Symfony per response()
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;// namespace per utilizzare @Route


class SaveProduct extends Controller {
    
    /**
    * @Route("/saveproduct")
    */
    public function createAction()
    {
    // 1. Crea i prodotti
    // primo prodotto ----------------------------------------------------------    
    $product = new Product();
    $product->setName('Keyboard');
    $product->setPrice(19.99);
    $product->setDescription('Ergonomic and stylish!');
    // -------------------------------------------------------------------------
    // secondo prodotto --------------------------------------------------------
    $anotherProduct = new Product();
    $anotherProduct->setName('Mouse');
    $anotherProduct->setPrice(5.99);
    $anotherProduct->setDescription('Really cool!');
    // -------------------------------------------------------------------------
    
    // debug code --------------------------------------------------------------
    echo 'Primo Debug';
    var_dump($product); // debug notare che id = 'null', non è un problema
    // il campo Id lo gestisce Doctrine automaticamente, Id resta nel DB anche alla cancellazione del prodotto
    var_dump($anotherProduct);
    // die('Stop Here'); // debug 
    
    // 2. accesso al DB --------------------------------------------------------
    $em = $this->getDoctrine()->getManager(); // carica il metodo di Doctrin per la gestione del DB
    // 3. INSERIMENTO PRIMO OGGETTO --------------------------------------------
    // tells Doctrine you want to (eventually) save the Product (no queries yet)
    $em->persist($product); // prepara l'oggetto in Cache per velocizzarsi ma NON salva ancora
    // actually executes the queries (i.e. the INSERT query)
    $em->flush(); // metodo flush() esegue INSERT
    // 4. INSERIMENTO SECONDO OGGETTO ------------------------------------------
    $em->persist($anotherProduct);
    $em->flush();
    // 5. RIMOZIONE SECONDO OGGETTO --------------------------------------------
    $em->remove($anotherProduct);
    $em->flush();
    
    // mostra id prelevandolo dall'oggetto $product, non sta leggendo dal DB
    return new Response(
            'Saved new product with id '.$product->getId()
            );
 
    }// END createAction()
    
}// END class Saveproduct

Come funziona?

1. Istanzio per creare 2 prodotti $product = new Product(); – $anotherProduct = new Product();

2. $em = $this->getDoctrine()->getManager(); – richiamo il metodo di Doctrine per la gestione del DB

3a. $em->persist($product); – richiamo il metodo persist per creare una query temporanea in cache
3b. $em->flush(); – avvia la query INSERT

4a. $em->remove($anotherProduct); – richiamo il metodo remove per creare una query temporanea in cache
4b. $em->flush(); – avvia la query DELETE

Bibliografia:
symfony.com/doc/current/doctrine.html
docs.doctrine-project.org
docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/basic-mapping.html#quoting-reserved-words

By |MySQL, PHP, Symfony, Web Design|Commenti disabilitati su Symfony – Databases and the Doctrine ORM

Symfony – Sign In – Simple Form with Object – Json – Array

Come creare un semplice form Sign In ed ottenere i dati in JSon

Il template .twig in app/Resources/views/default/new.html.twig


{# app/Resources/views/default/new.html.twig #}
{{ form_start(form) }}
{{ form_widget(form) }}
{{ form_end(form) }}

L’entità in src/AppBundle/Entity/Person.php


<?php

// src/AppBundle/Entity/Person.php
namespace AppBundle\Entity;

use Symfony\Component\Validator\Constraints as Assert; // serve per @Assert\...

class Person // dichiarazione esplicita dell'oggetto
{
    // -------------------------------------------------------------------------    
    // Proprietà ---------------------------------------------------------------
    // -------------------------------------------------------------------------
    
    /**
     * @Assert\NotBlank()
     */
    public $name;    
     /**
     * @Assert\NotBlank()
     */
    public $surname; 
    /**
     * @Assert\Email(
     *     message = "The email '{{ value }}' is not a valid email.",
     *     checkMX = true
     * )
     */
    public $email; 
    
    // -------------------------------------------------------------------------
    // Metodi ------------------------------------------------------------------
    // -------------------------------------------------------------------------
    
    // NB metodi get e set obbligatori per permettere a 'Form component' di symfony di funzionare correttamente
    public function getName() // ottieni
    {
        return $this->name; // assegna il valore che proviene dall'istanza $this->
    }

    public function setName($name) // setta
    {
        $this->name = $name;
    }
    
    // -------------------------------------------------------------------------

    public function getSurname() // ottieni 
    {
        return $this->surname;
    }

    public function setSurname($surname) // setta 
    {
        $this->surname = $surname;
    }
    
    // -------------------------------------------------------------------------
    
     public function getEmail() // ottieni 
    {
        return $this->email;
    }

    public function setEmail($email) // setta 
    {
        $this->email = $email;
    }
    
    // -------------------------------------------------------------------------
}

La classe SignIn in src/AppBundle/Controller/SignIn.php


<?php

// src/AppBundle/Controller/SignIn.php
namespace AppBundle\Controller;
 
use AppBundle\Entity\Person; // carica Person.php creato da me
use Symfony\Bundle\FrameworkBundle\Controller\Controller; // il bundle controller Symfont
use Symfony\Component\HttpFoundation\Request; // capacità do renderizzare html
use Symfony\Component\Form\Extension\Core\Type\TextType; // form di Symfony
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
 
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;// NECESSARIO per utilizzare @Route

class SignIn extends Controller // estende la classe Controller di Symfony
{
    /**
    * @Route("/signin")
    */
    public function signInAction(Request $request)
   {
       // creo il nuovo oggetto 
       $person = new Person();
      
       // 1. creo i contenuti HTML del form
       // invio Andrea, Tonin, andrea@email.it
       $form = $this->createFormBuilder($person)
           ->add('name', TextType::class) // il nome delle varibili è lo stesso di Person.php
           ->add('surname', TextType::class) 
           ->add('email', TextType::class) 
           ->add('save', SubmitType::class, array('label' => 'Create Person'))
           ->getForm();
        
       // 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 `$person` variable has also been updated
           $person = $form->getData();// ottieni i dati dal form
           
           // debug START ######################################################
           // Oggetto originale
           var_dump($person);  // mostra l'oggetto
           var_dump($person->name);  // mostra la varianbile name all'interno dell'oggetto
           // Conversione Json - NOTAZIONE JSON - è utile per trasportare i dati all'interno di una stringa
           $personJson = json_encode($person); // oggetto convertito in json format
           var_dump ($personJson); // mostra in json
           // Decodifica JSon - TORNA AD ESSERE UN OGGETTO
           $personDecoded = json_decode($personJson);
           var_dump ($personDecoded);
           var_dump($personDecoded->name);  // mostra la varianbile name all'interno dell'oggetto
           
           // Dummy Data, instanzio la classe inviando dei dati di esempio
            $anotherPerson = new Person();
            $anotherPerson->name = "Erica";
            $anotherPerson->surname = "Tonin";
            $anotherPerson->email = "erica@email.it";
           
           // Array
           $people =[]; // creo un array di persone vuoto
           array_push($people,$anotherPerson); // aggiungo id=0 dell'array
           array_push($people,$person); // aggiungo id=1 dell'array
           var_dump ($people); // visualizza il contenuto dell'array
           var_dump ($people[1]->name); // visualizzerà Andrea, array id 1 chiave name
           
           // altre operazioni con gli array
           // conta gli oggetti all'interno dell'array, visualizzerà 2
           var_dump(count($people)); 
           
           // renderizza tutto il contenuto dell'array di oggetti
           for ($i = 0; $i < count($people); $i++)// conteggia tutto il contenuto
           {
            echo $i . " " . ($people[$i]->name) . " " . ($people[$i]->surname) . " " . ($people[$i]->email) . "<br>";
           }
           
           // renderizza solo ad una particolare condizione
           for ($i = 0; $i < count($people); $i++)// conteggia tutto il contenuto
           {
                if (($people[$i]->name) === 'Erica') // se il valore è identico
                {
                echo 'La email di Erica è: ' . ($people[$i]->email) . "<br>";
                }
           }
           
           die ("Stop Here");  // interrompi qui la funzione
           // debug END ########################################################
       }// END validation
 
       // 2. Il form viene creato e renderizzato
       return $this->render('default/new.html.twig', array(
           'form' => $form->createView(),
       ));
   }   
    
}// END class SignIn

Puntare il browser a: http://localhost/symfonytest/first_test_symfony/web/signin

Inserire i dati ed inviare, verrà stampato a video:


C:\wamp64\www\symfonytest\first_test_symfony\src\AppBundle\Controller\SignIn.php:45:
object(AppBundle\Entity\Person)[316]
  public 'name' => string 'Andrea' (length=6)
  public 'surname' => string 'Tonin' (length=5)
  public 'email' => string 'andrea@email.it' (length=15)

C:\wamp64\www\symfonytest\first_test_symfony\src\AppBundle\Controller\SignIn.php:46:string 'Andrea' (length=6)

C:\wamp64\www\symfonytest\first_test_symfony\src\AppBundle\Controller\SignIn.php:49:string '{"name":"Andrea","surname":"Tonin","email":"andrea@email.it"}' (length=61)

C:\wamp64\www\symfonytest\first_test_symfony\src\AppBundle\Controller\SignIn.php:52:
object(stdClass)[390]
  public 'name' => string 'Andrea' (length=6)
  public 'surname' => string 'Tonin' (length=5)
  public 'email' => string 'andrea@email.it' (length=15)

C:\wamp64\www\symfonytest\first_test_symfony\src\AppBundle\Controller\SignIn.php:53:string 'Andrea' (length=6)

C:\wamp64\www\symfonytest\first_test_symfony\src\AppBundle\Controller\SignIn.php:65:
array (size=2)
  0 => 
    object(AppBundle\Entity\Person)[372]
      public 'name' => string 'Erica' (length=5)
      public 'surname' => string 'Tonin' (length=5)
      public 'email' => string 'erica@email.it' (length=14)
  1 => 
    object(AppBundle\Entity\Person)[316]
      public 'name' => string 'Andrea' (length=6)
      public 'surname' => string 'Tonin' (length=5)
      public 'email' => string 'andrea@email.it' (length=15)

C:\wamp64\www\symfonytest\first_test_symfony\src\AppBundle\Controller\SignIn.php:66:string 'Andrea' (length=6)

C:\wamp64\www\symfonytest\first_test_symfony\src\AppBundle\Controller\SignIn.php:70:int 2

0 Erica Tonin erica@email.it
1 Andrea Tonin andrea@email.it
La email di Erica è: erica@email.it

Stop Here

Come funziona?

1. Istanziata la classe $person = new Person(); e creato l’oggetto $person, vuoto, cone le sole chiavi.

2. Creato il form con il metodo di Symfony createFormBuilder()

3. Renderizzato il form con il metodo di Symfony return $this->render()

4. Invio i dati dal form, il metodo handleRequest($request); verifica che è stato inviato e aggiorna $person

5. Il contenuto di $person viene validato nell’entità Person.php

6. In signIn.php se $person è stato inviato ed è valido: $person = $form->getData();

7. nella sezione di debug gioco un po con i dati:
– mostro il dato come oggetto
– codifico il dato come json
– decodifico il dato da json
– creo un nuovo oggetto istanziando $anotherPerson = new Person();
– creo un array vuoto $people =[]
– inserisco nell’array i 2 oggetti precedentemente creati
– visualizzo i contenuti secondo la sintassi:

$people[1]->name
nomearray[id]->keyword

Il mio sito ufficiale: lucedigitale.com

By |JSON, PHP, Symfony, Web Design|Commenti disabilitati su Symfony – Sign In – Simple Form with Object – Json – Array

Symfony for beginners – Multipage Controller

Un semplice esempio per creare un Controller Multipagina per gestire contenuti dinamici in un template .twig

1. app\Resources\views\base.html.twig


<!-- app\Resources\views\base.html.twig -->
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>{% block title %}Welcome to my Company{% endblock %}</title>
        {% block stylesheets %}{% endblock %}
        <link rel="icon" type="image/x-icon" href="{{ asset('favicon.ico') }}" />
    </head>
    <body>
        {% block body %}{% endblock %}
        {% block javascripts %}{% endblock %}
    </body>
</html>

2. app\Resources\views\index.html.twig


{# app\Resources\views\index.html.twig #}

{% extends 'base.html.twig' %}

{% block body %}
<h1>This is one page</h1>
<strong>This is the page: {{pagetitle}}</strong>
<br>
{{navigationmenu | raw }}
<br>
<a href="#">Visit My company</a>
<br>
{{pagecontent}}
{% endblock %}

{% block stylesheets %}
<style>
    h1 { font-size: 36px; }
</style>
{% endblock %}

3. src\AppBundle\Controller\MyCompanyController.php


<?php
//src\AppBundle\Controller\MyCompanyController.php
namespace AppBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;  // namespace for route
use Symfony\Component\HttpFoundation\Response;               // namespace for http render
use Symfony\Bundle\FrameworkBundle\Controller\Controller;    // to extend Controller

class MyCompanyController extends Controller
{
    // proprietà comuni
    // protected perchè non vogliamo che venga modificata dall'esterno
    protected $menu = '<strong>The Navigation Bar:</strong><br>'
            . '<a href="/">Home</a><br>'
            . '<a href="aboutus">About Us</a><br>'
            . '<a href="services">Services</a><br>'
            . '<a href="contactus">Contact Us</a>'
            ; 
    
     /**
    * @Route("/")
    */
    public function homeAction() // sempre suffisso ...Action
    {
        // send the variable to a .twig template
        return $this->render('index.html.twig', array(
            'navigationmenu' => $this->menu, //$this è la sintassi per usare le proprietà
            'pagetitle' => 'Home',
            'pagecontent' => 'Content of Home',
        ));
    }// END home ------------------------------------------------------------
    /**
    * @Route("/aboutus")
    */
    public function aboutUsAction() // sempre suffisso ...Action
    {
        
        $number = mt_rand(0, 100); // this is plain PHP
        // send the variable to a .twig template
        return $this->render('index.html.twig', array(
            'navigationmenu' => $this->menu,
            'pagetitle' => 'About Us',
            'pagecontent' => 'Content of About Us and a number RNG '. $number,
        ));
    }// END aboutus ----------------------------------------------------------
    /**
    * @Route("/services")
    */
    public function servicesAction() // sempre suffisso ...Action
    {
        // send the variable to a .twig template
        return $this->render('index.html.twig', array(
            'navigationmenu' => $this->menu,
            'pagetitle' => 'Services',
            'pagecontent' => 'Content of Services',
        ));
    }// END services ---------------------------------------------------------
    /**
    * @Route("/contactus")
    */
    public function contactUsAction() // sempre suffisso ...Action
    {
        // send the variable to a .twig template
        return $this->render('index.html.twig', array(
            'navigationmenu' => $this->menu,
            'pagetitle' => 'Contact Us',
            'pagecontent' => 'Content of Contact Us',
        )); 
    }// END contacUs ---------------------------------------------------------
    
}// END class MyCompanyController

Puntare il browser alla homepage a: http://localhost/symfonytest/first_test_symfony/web/

Come funziona?

1. MyCompanyController.php

a. creo una proprietà ‘protected’ perchè non voglio che sia modificabile dall’esterno, questo garantirà maggior robustezza al mio codice. Dentro a $menu vi è il menù di navigazione comune a tutte le pagine.

b. ogni pagina è un metodo con:

– un percorso @Route

– un nome del metodo chiaro che ci aiuta a identificare il suo compito.
Ogni metodo deve avere il suffisso Action()

– invio al template ‘index.html.twig’ di un array di variabili
Notare che ‘$this->menu’ è la sintassi corretta per recuperare la proprietà all’interno della funzione.

2. index.html.twig

– estende ‘base.html.twig’

– riceve le variabili come plain text {{pagetitle}}

– riceve le variabili come HTML {{navigationmenu | raw }}, notare che il dato è raw

By |PHP, Symfony, Web Design|Commenti disabilitati su Symfony for beginners – Multipage Controller

Symfony lezioni di base – Creare un Form come Classe

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

By |PHP, Symfony, Web Design|Commenti disabilitati su Symfony lezioni di base – Creare un Form come Classe

Form Inside Controller – Oggetto Render Validazione

Il Form component per Symfony è un componente standalone che può essere utilizzato anche al di fuori di Symfony.

In questa lezione creeremo un form direttamente all’interno di un Controller:


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 con Dummy Data

1. Creare in src/AppBundle/Entity/Task.php


<?php

/// src/AppBundle/Entity/Task.php
namespace AppBundle\Entity;

class Task // dichiarazione esplicita dell'oggetto
{
    // proprietà o variabili non accessibile dall'esterno della classe
    protected $task;    // cose da fare
    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;
    }
}

2. Creare in 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 Symfony\Bundle\FrameworkBundle\Controller\Controller; // il bundle controller Symfont
use Symfony\Component\HttpFoundation\Request; // capacità do renderizzare html
use Symfony\Component\Form\Extension\Core\Type\TextType; // form di Symfony
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;// NECESSARIO per utilizzare @Route

class DefaultController extends Controller // estende la classe Controller di Symfony
{
	/**
	* @Route("/form")
	*/
    public function newAction(Request $request) // metodo
    {
        // Utilizzo della classe Task di Task.php per creare l'oggetto $task INIZIO -> crea $task
        $task = new Task();// creo un oggetto istanziando la classe Task
        $task->setTask('Write a blog post'); // assegno $task, le cose da fare
        $task->setDueDate(new \DateTime('tomorrow')); // setta la scadenza
        // Utilizzo della classe Task di Task.php per creare l'oggetto $task FINE

        // Creazione del form utilizzando le classi di Symfony INIZIO -> crea $form
        $form = $this->createFormBuilder($task)// invia al metodo createFormBuilder l'oggetto $task con tutte i dati
            // istruzioni per creare i TAG HTML INIZIO
            ->add('task', TextType::class)// invia al metodo add() assegnando la propietà 'task' di Task.php e la variabile statica 'TextType::class' che indica un campo di testo
            ->add('dueDate', DateType::class)// come sopra
            ->add('save', SubmitType::class, array('label' => 'Create Post'))// come sopra con aggiunta della label
            // istruzioni per creare i TAG HTML FINE
            ->getForm(); // questo metodo di Symfony restituisce il form
        // Creazione del form utilizzando le classi di Symfony FINE

        // ivia l'istruzione al template .twig inviando $form
        // la risposta finale è invio al metodo render() - template.twig - form - $form
        return $this->render('default/new.html.twig', array(
            'form' => $form->createView(),
        ));
    }
}

2. Creare in app/Resources/views/default/new.html.twig


{# app/Resources/views/default/new.html.twig #}
{{ form_start(form) }}
{{ form_widget(form) }}
{{ form_end(form) }}

Puntare il browser su: http://localhost/symfonytest/first_test_symfony/web/form

Come funziona?
Si avvia DefaultController.php:
1. Crea l’oggetto $task instanziando in Task.php la class Task
2. Crea l’oggetto $form con il metodo createFormBuilder() di Symfony
3. Renderizza il form inviandolo al template ,twig con il metodo render() di Symfony

NB: – $task = new Task(); – sono dummy data – dati di esempio!!!

Form senza Dummy Data

Ripuliamo dai dati generati come esempio matenendo solo il form


<?php

// src/AppBundle/Controller/DefaultController.php
namespace AppBundle\Controller;

use AppBundle\Entity\Task; // carica Task.php creato da me
use Symfony\Bundle\FrameworkBundle\Controller\Controller; // il bundle controller Symfont
use Symfony\Component\HttpFoundation\Request; // capacità do renderizzare html
use Symfony\Component\Form\Extension\Core\Type\TextType; // form di Symfony
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;// NECESSARIO per utilizzare @Route

class DefaultController extends Controller // estende la classe Controller di Symfony
{
	/**
	* @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
       $form = $this->createFormBuilder($task)
           ->add('task', TextType::class) // il nome delle varibili è lo stesso di Task.php
           ->add('dueDate', DateType::class)
           ->add('save', SubmitType::class, array('label' => 'Create Task'))
           ->getForm();
       
       // 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(),
       ));
   }
}

Puntare il browser su: http://localhost/symfonytest/first_test_symfony/web/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->createFormBuilder($task)

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()) {
– 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

Validazione

Come visto sopra $form->isValid() è una scorciatoia per scrivere $task->isValid()
Il controllo di validazione quindi verrà effettuato su direttamente sull’oggetto e non sul form come si fa di solito in HTML

Modifichiamo Task.php che contiene il nostro oggetto:


<?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;
    }
}

Notare:

– l’utilizzo del namspace

use Symfony\Component\Validator\Constraints as Assert;

– la notazione per la validazione:


     /**
     * @Assert\NotBlank()
     * @Assert\EqualTo("Andrea")
     */

Per $task verrà accettato solamente un campo non vuoto ed uguale ad “Andrea”
Se tento di inviare un campo vuoto o diverso da “Andrea” sarà restituito il controllo di validazione

Si può consultare la lista completa dei controlli di validazione a:
symfony.com/doc/current/validation.html

Bibliografia:
symfony.com/doc/current/forms.html
symfony.com/doc/current/validation.html

By |PHP, Symfony, Web Design|Commenti disabilitati su Form Inside Controller – Oggetto Render Validazione