fbpx

Symfony Data Transformer

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!

Zgarnij darmowy ebook i cotygodniową dawkę wiedzy

.
Tags:
Magdalena Limanówka-Kuciel
magdalena@panizkomputerem.pl

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.