Les dataTransformers

Les dataTransformers

Il existe deux types de dataTransformers : les modelTransformers et les viewTransformers.

Les premiers permettent de transformer la donnée modèle en donnée normalisée alors utilisable par la vue, et les seconds permettent de transformer la donnée normalisée en donnée vue.

Les données modèle sont celles que l’on récupère par la méthode getData, ou qui sont settées par la méthode setData (méthodes du formulaire)

Les données normalisées sont généralement identiques aux données modèles.

Les données vues sont utilisées pour remplir les champs. La méthode submit($data) du formulaire utilise le format de la vue lors de la soumission des formulaires.

Tout dépend de ce que nous voulons faire. S’il s’agit uniquement de modifier l’information soumise (enregistrer un champ en lettres capitales, par exemple, ou changer le format d’une date), alors ce sont les viewTransformers qu’il faut utiliser.

S’il faut convertir une donnée soumise par le formulaire en un objet, ou en un autre type, alors les modelTransformers sont plus appropriés.

Cas pratique : un champ texte avec un datepicker que nous voulons convertir en date pour la base de données.

class Article
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\Column(name="publication_date", type="date", length=255, nullable = true)
     */
    private $publicationDate;

...
}

 

Dans un premier temps, il faut déclarer le dataTransformer dans le formType :

->add(
    $builder->create(
        'publicationDate', 'text',
        array(
        'attr' => array('class' => 'datepicker')
        )
    )
    ->addModelTransformer(new TextToDateTimeDataTransformer())
)

 

datepicker

Le dataTransformer étant associé à notre champs dans le formulaire, il faut à présent coder ses deux fonctions : transform et reverseTransform.

1) Le dataTransformer va récupérer le champs texte lors de la soumission du formulaire et le convertir en objet dateTime par la fonction reverseTransform
2) Le dataTransformer, lors de l’édition d’un objet (url du type {objectID}/edit), va récupérer l’information en base de donnée (donc le datetime) et le convertir en champ texte par la fonction transform.

class TextToDateTimeDataTransformer implements DataTransformerInterface
{
    // quand info revient de l'extérieur (base de données, url, fichier texte, etc.), à l'affichage du formulaire lors d'un edit
    public function transform($datetime)
    {
        if (null === $datetime) {
            return '';
        }

        if (!is_object($datetime)) {
            throw new TransformationFailedException('Expected a datetime.');
        }

        return $datetime->format('d').DIRECTORY_SEPARATOR.$datetime->format('m').DIRECTORY_SEPARATOR.$datetime->format('Y');

    }

    // quand le formulaire est soumis
    public function reverseTransform($stringDate)
    {
        if (null === $stringDate) {
            return NULL;
        }

        if (!is_string($stringDate)) {
            throw new TransformationFailedException('Expected a string.');
        }

        return \DateTime::createFromFormat('d/m/Y', $stringDate);
    }
}

 

D’autres cas intéressants peuvent nécessiter l’utilisation d’un dataTransformer : transformer des données soumises sous forme d’array en une chaine de caractère séparée par des virgules (pour le cas de tags d’un article, par exemple), convertir un numéro d’un champ int en un objet enregistré en base, etc.

Imaginons que nous avons un champ texte en base de données, mais que nous avons un champ de type checkbox:

class Article
{
    const FILES_LIMIT = 3;

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

    /**
     * @var string
     *
     * @ORM\Column(name="tags", type="string", length=255)
     */
    private $tags;
...
}

tags

Dans un premier temps, il faut déclarer le dataTransformer dans le formType :

->add(
    $builder->create(
        'tags', 'choice',
        array(
        'choices' => array(
            'tag1' => 'tag 1',
            'tag2' => 'tag 2',
            'tag3' => 'tag 3',
            'tag4' => 'tag 4'
        ),
        'required' => false,
        'expanded' => true,
        'multiple' => true,
        'empty_value' => false
        )
    )
    ->addModelTransformer(new ArrayToDelimitedStringDataTransformer())
)

 

Puis nous codons le dataTransformer:

class ArrayToDelimitedStringDataTransformer implements DataTransformerInterface
{
    // quand info revient de l'extérieur (base de données, url, fichier texte, etc.), à l'affichage du formulaire lors d'un edit
    public function transform($string)
    {
        if (null !== $string && !is_string($string)) {
            throw new TransformationFailedException('Expected a string.');
        }
        $string = trim($string);

        if (empty($string)) {
            return array();
        }

        $values = explode(',', $string);
        if (0 === count($values)) {
            return array();
        }

        foreach ($values as &$value) {
            $value = trim($value);
        }

        return $values;
    }

    // quand le formulaire est soumis
    public function reverseTransform($array)
    {
        if (null === $array) {
            return '';
        }

        if (!is_array($array)) {
            throw new TransformationFailedException('Expected an array.');
        }

        $string = trim(implode(',', $array));

        return $string;
    }
}

 

Symfony2 comporte un certain nombre de dataTransformers natifs :

dataTransformers

Le code est disponible sur github: https://github.com/jpsymfony/forms-symfony2

 

Commentaires

Soyez le premier à laisser un commentaire !

Laisser un commentaire

Les champs obligatoires sont indiqués avec *