Symfony Data Transformer

Data transformery to ciekawy element, który zdarza mi się wykorzystywać przy okazji bardziej zaawansowanych formularzy. Bardzo przydaje się, gdy np. dane formularzu mają format tekstowy, w modelu wtedy musimy stworzyć również property o type string ale tak na prawdę będziemy musieli potem za każdym razem pamiętać, żeby przemapować go na jakiś inny format bądź obiekt. Najczęściej zdarza się to np. z datami. Wtedy kombinujemy jak to zrobić np. używając eventów formowych, a w rzeczywistości wystarczy nam właśnie Data transformer

Typy Data transformerów

Data transformer to nic innego jak warstwa między formularzem, a modelem danych, która może modyfikować dane wejściowe formularza w określony przez nas sposób zanim trafia one do modelu.

Żeby dobrze zrozumieć czym jest Data transformer najpierw musisz wiedzieć jak wygląda przepływ danych. Jak na obrazku powyżej w formularzach mamy trzy warstwy danych. Najwyższa czyli View Data, przechowuje dane dokładnie w takiej formie w jakiej użytkownik wpisze je do formularza. Norm Data jest rzadko używana wprost, dane w tej warstwie są zwykle takie same jak w Model Data. Ostatnia i najważniejsza to Model Data. Dane w tej warstwie do rzeczywiste dane, na których pracujemy w aplikacji. Jeśli wywołamy $form->getData() to właśnie z tej warstwy otrzymamy dane. Gdy tworzymy obiekt Modelu dla formularza to jest to warstwa Model Data.

Wyróżniamy dwa typy data transformerów: View Transformer i Model Transformer. Ten pierwszy bardzo rzadko wykorzystujemy, zmienia dane między View Data, a Norm Data. Tak jak wspomniałam Norm Data nie jest używany bezpośrednio, a Model Data jest najważniejszy. Oprócz bardzo szczególnych przypadków to właśnie Model Transformer jest odpowiedzią na nasze potrzeby, ponieważ działa między Norm Data, a Model Data.

Jak wygląda Data transformer

Data transformer musi implementować Interfejs DataTransformerInterface oraz posiadać dwie metody transform() i reverseTransform(). Na obrazku powyżej możesz zobaczyć, który działa w którą stronę.

<?php

declare(strict_types = 1);

namespace App\Form\DataTransformer;

use App\ValueObject\OrderId;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;

/**
 * Class OrderIdDataTransformer
 */
class OrderIdDataTransformer implements DataTransformerInterface
{
    /**
     * @param OrderId|null $value
     *
     * @return null|string
     */
    public function transform($value): ?string
    {
        if ($value) {
            if ($value instanceof OrderId) {
                return $value->getValue();
            }

            throw new TransformationFailedException('Invalid OrderId object');
        }

        return null;
    }

    /**
     * @param string|null $value
     *
     * @return OrderId|null
     */
    public function reverseTransform($value): ?OrderId
    {
        if ($value) {
            try {
                return new OrderId($value);
            } catch (\InvalidArgumentException $e) {
                throw new TransformationFailedException(sprintf('Invalid Bluemedia OrderId "%s" value', $value));
            }
        }

        return null;
    }
}

Transformer jest aplikowany już na konkretne pole formularza stąd w parametrach metod od razu mamy dostęp do konkretnej wartości, którą chcemy zmodyfikować.

Jak go używać?

<?php

declare(strict_types = 1);

namespace App\Form\Type;

use App\Form\DataTransformer\OrderIdDataTransformer;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;

class OrderType extends AbstractType
{
    private $transformer;

    public function __construct(OrderIdDataTransformer $transformer)
    {
        $this->transformer = $transformer;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('orderId', TextType::class));

        $builder->get('orderId')
            ->addModelTransformer($this->transformer);
    }
}

W tej samej metodzie w której budujemy formularz, po dodaniu pól, wystarczy wystarczy na odpowiednim polu get(‘orderId’) wywołać addModelTransformer i podać obiekt Transformera czy tak jak ja poprzez przekazanie go w konstruktorze czy po prostu poprzez new OrderIdDataTransformer(). W przypadku View Transformera należy wywołać analogicznie addViewTransformer.

To wszystko o Data transformerach, jeśli masz jakieś pytania to pisz śmiało w komentarzu!

Poprzedni artykułTwig – funkcje
Następny artykułTwig – filtry

Podobne posty

Jestem programistką, która lubi mieć ręce pełne roboty. Do życia potrzebuje komputera z internetem i kubka gorącej kawy. Więcej na stronie o mnie.

Comments

ZOSTAW ODPOWIEDŹ

Please enter your comment!
Please enter your name here