Michaël Gallego
Octobre 2012
Code source en ligne : https://github.com/bakura10/ZendFormWebinar
Un composant "fourre-tout" et complexe :
Zend\Form fournit de nombreux éléments par défaut :
Zend\InputFilter permet de :
Pour créer un InputFilter :
Utilisation des hydrateurs :
Plusieurs stratégies :
interface HydratorInterface
{
/**
* Extrait les valeurs de l'objet
*/
public function extract($object);
/**
* Hydrate $object avec les valeurs dans $data
*/
public function hydrate(array $data, $object);
}
class Foo
{
public $a = 'bar';
}
$hydrator = new \Zend\Stdlib\Hydrator\ObjectProperty();
var_dump($hydrator->extract(new Foo()));
// Affiche : array('a' => 'bar');
class Foo
{
public $a = 'bar';
}
$hydrator = new \Zend\Stdlib\Hydrator\ObjectProperty();
$object = $hydrator->hydrate(array('a' => 'baz'), new Foo());
var_dump($object);
// Affiche object(Foo)[201]
// public 'a' => string 'baz' (length=3)
Utilisation d'aides de vue dédiées :
Voyons un exemple…
Nous souhaitons créer un formulaire pour ajouter un concert :
namespace Application\Entity;
class Groupe
{
/** @var string */
public $nom;
/** @var string */
public $site;
}
namespace Application\Entity;
class Concert
{
/** @var Groupe */
public $groupe;
/** @var int */
public $nombreSieges;
}
Les entités "correspondent" à un fieldset :
namespace Application\Form;
use Application\Entity\Groupe;
use Zend\Form\Fieldset;
use Zend\Stdlib\Hydrator\ObjectProperty;
class GroupeFieldset extends Fieldset
{
public function __construct()
{
parent::__construct('groupe');
$this->setObject(new Groupe())
->setHydrator(new ObjectProperty());
// Ajout des éléments...
[…]
}
}
// Dans GroupeFieldset::__construct
$this->add(array(
'name' => 'nom',
'options' => array(
'label' => 'Nom'
)
));
$this->add(array(
'type' => 'Zend\Form\Element\Url',
'name' => 'site',
'options' => array(
'label' => 'Site web'
)
));
$this->add(array(
'name' => 'site',
'options' => array(
'label' => 'Site web'
),
'attributes' => array(
'required' => 'required',
'placeholder => 'http://'
)
));
use Zend\InputFilter\InputFilterProviderInterface;
class GroupeFieldset extends Fieldset
implements InputFilterProviderInterface
{
public function getInputFilterSpecification()
{
return array(
'nom' => array(
'required' => true,
'filters' => array(
array('name' => 'StringTrim')
),
'validators' => array(
array('name' => 'StringLength', array('max' => 48))
)
)
);
}
}
class ConcertFieldset extends Fieldset
{
public function __construct()
{
parent::__construct('concert');
$this->setObject(new Concert())
->setHydrator(new ObjectProperty());
// Ajout des éléments
[…]
}
}
// Dans ConcertFieldset::construct__()
$this->add(array(
'type' => 'Application\Form\GroupeFieldset',
'name' => 'groupe',
'options' => array(
'label' => 'Groupe'
)
));
$this->add(array(
'type' => 'Zend\Form\Element\Number',
'name' => 'nombreSieges',
'options' => array(
'label' => 'Nombre de sièges dans la salle'
),
'attributes' => array(
'min' => 50
)
));
namespace Application\Form;
use Zend\Form\Form;
use Zend\Stdlib\Hydrator\ObjectProperty;
class CreerConcert extends Form
{
public function __construct()
{
parent::__construct('creer-concert-form');
$this->setHydrator(new ObjectProperty());
// Ajout des éléments
[…]
}
}
// Dans Application\Form\CreerConcert::__construct
$this->add(array(
'type' => 'Application\Form\ConcertFieldset',
'name' => 'concert',
'options' => array(
'use_as_base_fieldset' => true
)
));
$this->add(array(
'type' => 'Zend\Form\Element\Submit',
'name' => 'submit',
'attributes' => array(
'value' => 'Créer ce concert !',
'class' => 'btn-success'
)
));
// dans application/create-concert.phtml
$form = $this->form;
$form->setAttribute('action', $this->url(null, array(), true))
->prepare();
$concert = $form->get('concert');
$groupe = $concert->get('groupe');
echo $this->form()->openTag($form); // <form action="…">
echo $this->formLabel($concert->get('nombreSieges'));
echo $this->formNumber($concert->get('nombreSieges'));
echo $this->formElementErrors($concert->get('nombreSieges'));
echo $this->formRow($groupe->get('nom'));
echo $this->formRow($groupe->get('site'));
echo $this->formSubmit($form->get('submit'));
echo $this->form()->closeTag($form); // </form>
public function createConcertAction()
{
$form = new CreerConcert();
if ($this->request->isPost()) {
$concert = new Concert();
$form->bind($concert);
$form->setData($this->request->getPost());
if ($form->isValid()) {
var_dump($concert);
}
}
return new ViewModel(array(
'form' => $form
));
}
Formulaire de mise à jour : nous ne souhaitons pouvoir modifier que le nombre de places dans la salle :
class UpdateConcert extends Form
{
public function __construct()
{
parent::__construct('update-concert-form');
$this->setHydrator(new ObjectProperty());
$this->add(array(
'type' => 'Application\Form\ConcertFieldset',
'name' => 'concert',
'options' => array(
'use_as_base_fieldset' => true
)
));
$this->setValidationGroup(array(
'concert' => array( 'nombreSieges')
));
public function updateConcertAction()
{
$form = new UpdateConcert();
$concert = [...]; // récupère de la base de données par exemple
$form->bind($concert);
if ($this->request->isPost()) {
$form->setData($this->request->getPost());
if ($form->isValid()) {
var_dump($concert);
}
}
return new ViewModel(array(
'form' => $form
));
}
Dans un formulaire de mise à jour, on bind l'objet AVANT d'utiliser le formulaire, afin de le pré-remplir avec les valeurs déjà existantes.
Les formulaires de Zend Framework 2 sont très puissants :
Si vous utilisez Doctrine 2…
Quelques liens utiles pour approfondir :
Demain : webinar sur les Modules à 14h30 (présenté par Vincent Blanchon) Formations ZF 2 (en classe ou en ligne) : http://bit.ly/R7PWzZ
Merci à Rob Allen (@akrabat) pour son aide
| Table of contents | t |
|---|---|
| Exposé | ESC |
| Autoscale | e |
| Full screen slides | f |
| Presenter view | p |
| Source files | s |
| Slide numbers | n |
| Blank screen | b |
| Notes | 2 |
| Help | h |