Symfony YAML vs XML JSON

YAML è una notazione nata nel 2001 per la serializzazione standard dei dati come XML ed è la notazione pricipale per Symfony.
YAML significa ‘YAML Ain’t Markup Language’ cioè è una notazione senza marker, infatti a differenza di XML non presenta marker, ma la struttura dei dati è mostrata tramite l’indentazione (l’utilizzo degli spazi e dell’andare a capo). Vediamo di seguito degli esempi pratici.

OGGETTO PHP


$house = array(
  'family' => array(
    'name'     => 'Doe',
    'parents'  => array('John', 'Jane'),
    'children' => array('Paul', 'Mark', 'Simone')
  ),
  'address' => array(
    'number'   => 34,
    'street'   => 'Main Street',
    'city'     => 'Nowheretown',
    'zipcode'  => '12345'
  )
);

YAML sintassi lunga


house:
  family:
    name:     Doe
    parents:
      - John
      - Jane
    children:
      - Paul
      - Mark
      - Simone
  address:
    number: 34
    street: Main Street
    city: Nowheretown
    zipcode: "12345"

YAML sentassi breve


house:
  family: { name: Doe, parents: [John, Jane], children: [Paul, Mark, Simone] }
  address: { number: 34, street: Main Street, city: Nowheretown, zipcode: "12345" }

Notare per gli array [], per gli hash {}

Un altro esempio comparativo YAMS XML JSON

XML


<people>
    <person>
        <firstName>Charles</firstName> <lastName>Schulz</lastName>
    </person>
    <person>
        <firstName>Walt</firstName> <middleName>Elias</middleName>
        <lastName>Disney</lastName>
    </person>
    <person>
        <firstName>Gary</firstName> <lastName>Larson</lastName>
    </person>
</people>

JSON


{
  “people”: [
    { “person”: {
         “firstName”: “Charles”,
         “lastName”: “Schulz”
         }
    },
    { “person”: {
         “firstName”: “Walt”,
         “middleName”: “Elias”,
         “lastName”: “Disney”
         }
    },
    { “person”: {
         “firstName”: “Gary”,
         “lastName”: “Larson”
         }
    }
  ]
}

YAML


people: 
  - 
    person: {firstName: Charles, lastName: Schulz }
  - 
    person:
       firstName: Walt
       middleName: Elias
       lastName: Disney
       characters: [ Mickey, Donald, Goofy ] 
  - 
    person:
       firstName: Gary
       lastName: Larson

By |PHP, Symfony, Web Design|Commenti disabilitati su Symfony YAML vs XML JSON

Symfony – Translations and Internationalization

Internationalization è un termine informatico che indica il processo di design di un software atto a renderlo adattabile a linguaggi e regioni differenti. Internationalization può essere abbreviato con la sigla ‘i18n’. Per approfondire vedi en.wikipedia.org/wiki/Internationalization_and_localization.

Symfony ha dei componenti studiati apposta per la traduzione dei testi utilizzando delle traduzioni pre-impostate.

Translator Service – PHP array

1. Creiamo il seguente Controller in src/AppBundle/Controller/Traduttore.php


<?php

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

use Symfony\Component\HttpFoundation\Response;// namespace per response()
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;// NECESSARIO per utilizzare @Route

use Symfony\Component\Translation\Translator; // per Translator()
use Symfony\Component\Translation\Loader\ArrayLoader; // per ArrayLoader()

class Traduttore {
    
    /**
    * @Route("/traduci")
    */
    public function translationAction()
   {
        $translator = new Translator('fr_FR'); // istanzia la classe Translator di Symfony
        $translator->addLoader('array', new ArrayLoader()); // crea l'array con le traduzioni
        $translator->addResource('array', array(
                                               'Symfony is great!' => 'J\'aime Symfony!',
                                               ), 'fr_FR'); // francese

        //                  ->traduci recuperando i dati array chiave-=valore
        var_dump($translator->trans('Symfony is great!'));// renderizza J'aime Symfony
   
    return new Response('FINE TRADUZIONE');
   }
    
}// END class

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

Renderizza:

C:\wamp64\www\symfonytest\first_test_symfony\src\AppBundle\Controller\Traduttore.php:25:string ‘J’aime Symfony!’ (length=15)
FINE TRADUZIONE

Il mio sito ufficiale:
lucedigitale.com

Bibliografia:
symfony.com/doc/current/translation.html

By |PHP, Symfony, Web Design|Commenti disabilitati su Symfony – Translations and Internationalization

PHP Lezione Avanzata – Classi Astratte

Classi Astratte

L’Astrazione dei Dati viene utilizzata per gestire al meglio la complessità di un programma, ovvero viene applicata per decomporre sistemi software complessi in componenti più piccoli e semplici.

Creando un esempio semplice.

Class: Animale
Metodi: mangia() respira() peso() altezza() e tutto quello che può caratterizzare un animale

Bisognerebbe però definire le singole istanze $cane = new Animale(); $gatto = new Animale(); etc…
In questo caso non possiamo creare infinite istanze per ogni tipo di animale, quindi Animale è una Classe Astratta, cioè una classe che non può essere istanziata. L’unica cosa a cui ci può servire è per ottenere delle classi derivate più specifiche.

La struttura sarà la seguente:

Class: Animale
1/2 Metodi + Motodi Astratti che sono solo una definizione del metodo stesso

Class: Cane
fornisce obbligatoriamente l’implementazione dei Metodi Astratti

Class: Gatto
fornisce obbligatoriamente l’implementazione dei Metodi Astratti

etc…

In PHP utilizziamo la keyword ‘abstract’

LA CLASSE ASTRATTA


// Team A - Class Product
abstract class Product {
 
    // proprietà pubbliche
    public $name;
    public $price;
 
    // metodi pubblici
    public function __construct($name, $price) {
        $this->name = $name;
        $this->price = $price;   
    }
     
    public function getName() {
        return $this->name;
    }
     
    public function getPrice() {
        return $this->price;
    }
 
    // metodi astratti contengono SOLO delle definizioni
    abstract public function buyProduct($pid, $quantity);
    abstract public function sellProduct($pid, $quantity);
 
}

LE CLASSI CHE ESTENDONO LA CLASSE ATRATTA


// Team B - Class InProduct
class InProduct extends Product {
 
    public function buyProduct($pid, $quantity) {
     
        // connettiamoci al nostro database locale per ottenere i prodotti che dobbiamo comprare con la quanità indicata...
        $prods = connect_to_my_local_db($db->login(), $quantity);
        $prods->sendmail("buy");
         
        // ...
     
    }
     
    public function sellProduct($pid, $quantity) {
     
        // connettiamoci al nostro database locale per ottenere i prodotti che dobbiamo vendere con la quanità indicata...
        $prods = connect_to_my_local_db($db->login(), $quantity);
        $prods->sendmail("sell");
         
        // ...
     
    }
 
}
 
 
// Team C - Class OutProduct
class OutProduct extends Product {
 
    public function buyProduct($pid, $quantity) {
     
        // connettiamoci al database del partner per ottenere i prodotti che dobbiamo comprare con la quanità indicata...
        $prods = connect_to_partner_db($db->login(), $quantity);
        $prods->sendmail("buy");
         
        // ...
     
    }
     
    public function sellProduct($pid, $quantity) {
     
        // connettiamoci al database del partner per ottenere i prodotti che dobbiamo vendere con la quanità indicata...
        $prods = connect_to_partner_db($db->login(), $quantity);
        $prods->sendmail("sell");
         
        // ...
     
    }
 
}

Ciò che è importante capire, è che nonostante le classi InProduct ed OutProduct siano create da diversi team di sviluppo, esse assumono una forma comune, coerente con quella indicata dalla classe astratta Product.

Se volessi creare un’API:


$pen = new InProduct("penna", 3.50);
$pencil = new OutProduct("matita", 3.50);
 
// vendiamo la penna
$pen->sellProduct(1102, 1);
 
// compriamo una matita
$pencil->buyProduct(3498, 1);

Come funziona?
1. $pen = new InProduct(“penna”, 3.50); – creo un’istanza di class InProduct extends Product {

2. $pen->sellProduct(1102, 1); – invoca public function sellProduct($pid, $quantity)

3. $pid, $quantity è comune a – function sellProduct($pid, $quantity) – che risalendo estende – extends Product – che risalendo definisce – abstract public function sellProduct($pid, $quantity);

4. idem per – buyProduct($pid, $quantity) – che deve avere ($pid, $quantity) – perchè così indicato da – abstract public function buyProduct($pid, $quantity);

Il mio sito ufficiale:
www.lucedigitale.com

Bigliografia:
www.html.it/pag/18355/utilizzare-le-classi-astratte/

By |PHP, Web Design|Commenti disabilitati su PHP Lezione Avanzata – Classi Astratte

Symfony – Simple Registration Form – Doctrine

Creare un semplice form di registrazione con Symfony e Doctrine.
Il form è funzionante e pronto all’uso.

0. Se è la prima volta che utilizziamo il DB, procediamo con il setup come mostrato nella lezione precedente a:
www.lucedigitale.com/blog/symfony-databases-and-the-doctrine-orm/

1. Creiamo il Database da PhpMyAdmin:

Database: test_project
Tabella: app_users
Campi:
– Id char(11) AUTO_INCREMENT
– username char (25) UNIQUE
– password char (60) UNIQUE
– email char (60) UNIQUE

2. Creiamo l’entità User in src/AppBundle/Entity/User.php


<?php

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

use Doctrine\ORM\Mapping as ORM; // uso Doctrine

use Symfony\Component\Validator\Constraints as Assert; // Uso la validazione
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; // Uso la validazione

use Symfony\Component\Security\Core\User\UserInterface;// usa il sistema Symfony per gestire gli utenti

/**
 * @ORM\Entity
 * @ORM\Table(name="app_users")
 * @UniqueEntity(fields="email", message="Email already taken")
 * @UniqueEntity(fields="username", message="Username already taken")
 */
class User implements UserInterface// aggiungi i metodi seguenti alla classe UserInterface di Symfony
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=255, unique=true)
     * @Assert\NotBlank()
     * @Assert\Email()
     */
    private $email;

    /**
     * @ORM\Column(type="string", length=255, unique=true)
     * @Assert\NotBlank()
     */
    private $username;

    /**
     * @Assert\NotBlank()
     * @Assert\Length(max=4096)
     */
    private $plainPassword; // la password in chiaro, non è salvata nel DB, infatti non abbiamo @ORM ma solo una validazione

    /**
     * The below length depends on the "algorithm" you use for encoding
     * the password, but this works well with bcrypt.
     *
     * @ORM\Column(type="string", length=64)
     */
    private $password; // la password criptata con bcript

    // other properties and methods
    // metodi GET e SET necessari per il funzionamento del form di Symfony

    public function getEmail()
    {
        return $this->email;
    }

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

    public function getUsername()
    {
        return $this->username;
    }

    public function setUsername($username)
    {
        $this->username = $username;
    }

    public function getPlainPassword()
    {
        return $this->plainPassword;
    }

    public function setPlainPassword($password)
    {
        $this->plainPassword = $password;
    }

    public function getPassword()
    {
        return $this->password;
    }

    public function setPassword($password)
    {
        $this->password = $password;
    }

    // ritorna NULL percho bcrypt gestisce il seme per criptare le password
    public function getSalt()
    {
        // The bcrypt algorithm doesn't require a separate salt.
        // You *may* need a real salt if you choose a different encoder.
        return null;
    }

    // other methods, including security methods like getRoles()
    
    public function getRoles()// i ruoli concessi all'utente
    {
        return array('ROLE_USER');
    }

    public function eraseCredentials()// rimuove i dati sensibili dell'utente
    {
    }
    
    // Serialize
    // Alla fine di ogni - request - l'oggetto User viene trasformato in un array (serialize) e salvato nella sessione
    // Alla richiesta successiva viene ricaricato dalla sessione e riconvertito (unserialize)
    /** @see \Serializable::serialize() */
    public function serialize()
    {
        return serialize(array(
            $this->id,
            $this->username,
            $this->password,
            // see section on salt below
            // $this->salt,
        ));
    }

    /** @see \Serializable::unserialize() */
    public function unserialize($serialized)
    {
        list (
            $this->id,
            $this->username,
            $this->password,
            // see section on salt below
            // $this->salt
        ) = unserialize($serialized);
    }
}// END Class

Come funziona?

Indico a Symfony dove trovare questo file che contiene la classe che sarà caricata come namespace


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

Carico i namespace


use Doctrine\ORM\Mapping as ORM; // uso Doctrine

use Symfony\Component\Validator\Constraints as Assert; // Uso la validazione
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; // Uso la validazione

use Symfony\Component\Security\Core\User\UserInterface;// usa il sistema Symfony per gestire gli utenti

Aggiungo i metodi alla classe UserInterface di Symfony


class User implements UserInterface...

Dichiaro le proprietà della classe e le loro caratteristiche SQL


     /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

Metodi GET e SET necessari a Symfony


public function getEmail()
    {
        return $this->email;
    }

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

Altre note:

getSalt() – non serve per il bcrypt ma va esplicitata obbligatoriamente o ritorna errore
getRoles() – anche se NULL va esplicitata obbligatoriamente o ritorna errore
eraseCredentials() – anche se NULL va esplicitata obbligatoriamente o ritorna errore

$plainPassword – non viene salvata nel DB ma solo validata @Assert\NotBlank() …

3. Modifichiamo app/config/security.yml, configuro i parametri di security per puntare a User.php e al DB app_users

In particolare notiamo:

– encoders: AppBundle\Entity\User: algorithm: bcrypt
-> usa l’algoritmo bcrypt per criptare la password

– app_users: entity: class: AppBundle:User property: username
-> come gli utenti vengono caricati tradotto -> ‘nometabella’: in ‘AppBundle/Entity/User.php’ proprietà ‘username’


# To get started with security, check out the documentation:
# http://symfony.com/doc/current/security.html

# app/config/security.yml
security:
    encoders:
        AppBundle\Entity\User:
            algorithm: bcrypt

    # http://symfony.com/doc/current/security.html#b-configuring-how-users-are-loaded
    providers:
        in_memory:
            memory: ~
        app_users:
            entity:
                class: AppBundle:User
                property: username
                # if you're using multiple entity managers
                # manager_name: customer

    firewalls:
        # disables authentication for assets and the profiler, adapt it according to your needs
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false

        main:
            anonymous: ~
            # activate different ways to authenticate
            pattern:    ^/
            http_basic: ~
           

            # http://symfony.com/doc/current/security.html#a-configuring-how-your-users-will-authenticate
            #http_basic: ~

            # http://symfony.com/doc/current/cookbook/security/form_login_setup.html
            #form_login: ~

4. Creiamo in src/AppBundle/Form/UserType.php il form come classe in modo che sia riusabile con facilità


<?php

// src/AppBundle/Form/UserType.php
namespace AppBundle\Form;

// carico User.php
use AppBundle\Entity\User;

// carico i namespace per il creare il form
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;

class UserType extends AbstractType // Estende la classe Symfony AbstractType{} 
{
    public function buildForm(FormBuilderInterface $builder, array $options) // metodo di AbstractType{}
    {
        $builder
            ->add('email', EmailType::class) // la casella email
            ->add('username', TextType::class) // la casella username
            // la casella password e repeat password    
            ->add('plainPassword', RepeatedType::class, array(
                'type' => PasswordType::class,
                'first_options'  => array('label' => 'Password'),
                'second_options' => array('label' => 'Repeat Password'),
            ))
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => User::class,
        ));
    }
}

5. Creiamo il controller per renderizzare il form a src/AppBundle/Controller/RegistrationController.php


<?php

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

use AppBundle\Form\UserType;// UserType.php
use AppBundle\Entity\User; // User.php

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; // @Route

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

use Symfony\Component\HttpFoundation\Request;

class RegistrationController extends Controller
{
    /**
     * @Route("/register", name="user_registration")
     */
    public function registerAction(Request $request)
    {
        // 1) build the form
        $user = new User(); // istanziamo l'oggetto di User.php
        $form = $this->createForm(UserType::class, $user);

        // 2) controlla se il bottone - submit - è stato premuto
        $form->handleRequest($request);
        
        // se l'oggetto user è submit AND validato
        if ($form->isSubmitted() && $form->isValid()) {

            // 3) Encode the password (you could also do this via Doctrine listener)
            $password = $this->get('security.password_encoder')
                ->encodePassword($user, $user->getPlainPassword());
            $user->setPassword($password);

            // 4) save the User!
            $em = $this->getDoctrine()->getManager();
            $em->persist($user);// prepara in cache i dati
            $em->flush(); // scrivi i dati nel DB

            // ... do any other work - like sending them an email, etc
            // maybe set a "flash" success message for the user

             return $this->redirect('http://symfony.com');
        }

        return $this->render(
            'registration/register.html.twig',
            array('form' => $form->createView())
        );
    }
}

6. Creiamo il Template app/Resources/views/registration/register.html.twig


{# app/Resources/views/registration/register.html.twig #}

{{ form_start(form) }}
    {{ form_row(form.username) }}
    {{ form_row(form.email) }}
    {{ form_row(form.plainPassword.first) }}
    {{ form_row(form.plainPassword.second) }}

    <button type="submit">Register!</button>
{{ form_end(form) }}

7. Puntiamo il browser a: http://localhost/symfonytest/first_test_symfony/web/register

Il form in automatico restituirà un messaggio di errore all’utente se:
– username è già stato preso
– email è già stata presa
– password è già stata presa
– password e repeat password non sono uguali

Il mio sito ufficiale:
lucedigitale.com

Bibliografia:
symfony.com/doc/current/doctrine/registration_form.html

By |MySQL, PHP, Symfony, Web Design|Commenti disabilitati su Symfony – Simple Registration Form – Doctrine

Symfony – Load Security Users from the Database – Doctrine

Caricare gli utenti attivi da un database con Symfony e Doctrine.
Il codice è solo teorico, non è pronto all’uso.
Vedere la lezione successiva ‘Symfony – Simple Registration Form – Doctrine’ per testare del codice pronto all’uso.

1. Creiamo il Database da PhpMyAdmin:

Database: test_project
Tabella: app_users
Campi:
– Id char(11) AUTO_INCREMENT
– username char (25) UNIQUE
– password char (60) UNIQUE
– email char (60) UNIQUE
– is_active BOOLEAN -> se l’utente è abilitato

2. Creiamo l’entità src/AppBundle/Entity/User.php


<?php

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

// namespace per usare Doctrine
use Doctrine\ORM\Mapping as ORM; 
// namespace per gestire gli Utenti e ottenere le password criptate
use Symfony\Component\Security\Core\User\UserInterface;

/**
 * @ORM\Table(name="app_users")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
 */

// implements aggiunge questi metodi a UserInterface di Symfony
class User implements UserInterface, \Serializable
{
    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=25, unique=true)
     */
    private $username;

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

    /**
     * @ORM\Column(type="string", length=60, unique=true)
     */
    private $email;

    /**
     * @ORM\Column(name="is_active", type="boolean")
     */
    private $isActive;

    public function __construct()
    {
        $this->isActive = true; // costruttore se l'utente è attivo
        // may not be needed, see section on salt below
        // $this->salt = md5(uniqid(null, true));
    }

    public function getUsername()
    {
        return $this->username;
    }

    // il seme o sale utilizzato per l'encode della password    
    // se uso bcrypt non è necessario perchè gestisce il seme automaticamente, e il metodo ritorna null
    public function getSalt() 
    {
        // you *may* need a real salt depending on your encoder
        // see section on salt below
        return null;
    }

    public function getPassword()
    {
        return $this->password;
    }

    public function getRoles()// i ruli concessi all'utente
    {
        return array('ROLE_USER');
    }

    public function eraseCredentials()// rimuove i dati sensibili dell'utente
    {
    }

    // Serialize
    // Alla fine di ogni - request - l'oggetto User viene trasformato in un array (serialize) e salvato nella sessione
    // Alla richiesta successiva viene ricaricato dalla sessione e riconvertito (unserialize)
    /** @see \Serializable::serialize() */
    public function serialize()
    {
        return serialize(array(
            $this->id,
            $this->username,
            $this->password,
            // see section on salt below
            // $this->salt,
        ));
    }

    /** @see \Serializable::unserialize() */
    public function unserialize($serialized)
    {
        list (
            $this->id,
            $this->username,
            $this->password,
            // see section on salt below
            // $this->salt
        ) = unserialize($serialized);
    }
}

3. Modifichiamo app/config/security.yml


# To get started with security, check out the documentation:
# http://symfony.com/doc/current/security.html

# app/config/security.yml
security:
    encoders:
        AppBundle\Entity\User:
            algorithm: bcrypt

    # http://symfony.com/doc/current/security.html#b-configuring-how-users-are-loaded
    providers:
        in_memory:
            memory: ~
        test_project:
            entity:
                class: AppBundle:User
                property: username
                # if you're using multiple entity managers
                # manager_name: customer

    firewalls:
        # disables authentication for assets and the profiler, adapt it according to your needs
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false

        main:
            anonymous: ~
            # activate different ways to authenticate
            pattern:    ^/
            http_basic: ~
           

            # http://symfony.com/doc/current/security.html#a-configuring-how-your-users-will-authenticate
            #http_basic: ~

            # http://symfony.com/doc/current/cookbook/security/form_login_setup.html
            #form_login: ~

Configuro i parametri di security per puntare a User.php


security:
    encoders:
        AppBundle\Entity\User:
            algorithm: bcrypt

...

test-project:
    entity:
         class: AppBundle:User
                property: username

Bibliografia:
symfony.com/doc/current/security/entity_provider.html#security-serialize-equatable
api.symfony.com/3.2/Symfony/Component/Security/Core/User/UserInterface.html#method_getRoles

By |MySQL, PHP, Symfony, Web Design|Commenti disabilitati su Symfony – Load Security Users from the Database – Doctrine