Twig: przyspiesz generowanie swoich szablonów
Agencja internetowa » Wiadomości cyfrowe » Twig: przyspiesz generowanie swoich szablonów

Twig: przyspiesz generowanie swoich szablonów

Ostatnio poprosiłem siebie o zastanowienie się nad rozwiązaniami oferowanymi przez Twig w celu uzyskania dostępu do właściwości obiektu lub tablicy.

Dostęp do właściwości obiektu

Twig został zaprojektowany, aby uprościć nasze szablony, zarówno pod względem kodu, jak i czystości. Został również zaprojektowany, aby umożliwić integratorom, czyli osobom, które nie wszystkie posiadają wiedzę programistyczną, łatwy dostęp do właściwości obiektu lub innych. Dzieje się tak dzięki uproszczonej składni.

Dopiero wtedy, będąc przede wszystkim programistą, zadałem sobie pytanie, jak twig radzi sobie z ustaleniem, która metoda obiektu ma zostać wywołana.

Składnia gałązki

W poniższym kodzie założę, że używam klasy jak poniżej.

1
2
3
4
5
6
7
8
9
10
11
12
13
klasa przedmiot
{
prywatny $Nazwa;
publiczny $nazwa użytkownika;
publiczny funkcjonować pobierzNazwę() {
powrót $ to-> imię;
}
publiczny funkcjonować pobierz nazwę użytkownika() {
powrót $ to-> nazwa użytkownika;
}
}

W ten sposób wywołam mój szablon z kontrolera Symfony.

1
2
3
publiczny funkcjonować indeksAkcja() {
powrót szyk("obiekt" => $obiekt);
}

Jak na razie wszystko jest jasne. Mój obiekt wygląda dokładnie tak, jak obiekty, których mogę użyć w moich projektach.

Parsowanie deklaracji w Twig

1
{{ object.name }}

Od teraz zobaczymy, jak Twig radzi sobie z naszymi połączeniami. Tutaj prosimy Twiga o przyjęcie wartości Nazwa mojego obiektu, z wyjątkiem tego, że dla Twiga, który w końcu jest tylko prostym wywołaniem PHP, ta zmienna jest niedostępna. Dlatego Twig dodał proxy do abstrakcji i zobaczył, jakie właściwości i metody są dostępne.

Twig poprosi zatem w poniższej kolejności o sprawdzenie obiektu.

  1. Zobacz, czy przedmiot jest tablicą i if Nazwa jest kluczem;
  2. Zobacz, czy przedmiot jest obiektem i jeśli Nazwa jest dostępnym atrybutem;
  3. Zobacz, czy przedmiot jest obiektem i jeśli Nazwa jest metodą;
  4. Zobacz, czy przedmiot jest obiektem i jeśli pobierzNazwę jest metodą;
  5. Zobacz, czy przedmiot jest obiektem i jeśli jest imię jest metodą.
    Tutaj, z notacją, której użyliśmy, musieliśmy czekać, aż czwarty warunek dotrze do naszego elementu. Ponieważ Nazwa nie jest dostępnym atrybutem ani metodą.

    1
    {{ object.username }}

W tym przypadku próbujemy uzyskać dostęp nazwa użytkownika. Ten atrybut jest atrybutem publicznym (w Symfony rzadko spotykałem się z takim przypadkiem). Musimy czekać na drugi warunek.

1
{{ object.getName() }}

W naszym trzecim przypadku próbuję bezpośrednio wywołać moją metodę. Otrzymuję wynik z trzeciego warunku, który jest szybszy.

1
{{ object.getUsername() }}

W naszym czwartym i ostatnim przypadku staram się bezpośrednio użyć mojej metody. Otrzymuję wynik z trzeciego warunku. W tym przypadku postawiłem dodatkowy warunek dostępu do mojej wartości.

Interpretacja szablonów Twig

Kiedy spojrzałem na ten szczegół, pomyślałem o tym, jak twórcy Twig mogli zrobić buforowanie i kompilację szablonów. Nie zajęło mi dużo czasu dojście do wniosku, że przy niewielkiej ilości informacji i swobodzie, jaką oferuje menedżer szablonów, nasze pliki są po prostu przepisywane na język PHP w sposób podobny do tego, co moglibyśmy zrobić całkowicie. Możesz także sam się o tym przekonać, zaglądając do folderu pamięci podręcznej.

1
2
{# Gałąź szablonu #}
{{ object.name }}
Szablon zinterpretowany w PHP
1
echo twig_escape_filter($this->env, $this->getAttribute((isset($kontekst["obiekt"]) ? $context["obiekt"] : $this->getContext($kontekst, "obiekt")), „nazwa”), „html”, zero, prawda);

Pierwszy blok pasuje do tego, co zanotowałem w moim szablonie twig, drugi blok pasuje do przetłumaczonej wersji, którą znalazłem w folderze pamięci podręcznej.

Zauważmy, że gałąź została przetłumaczona na język PHP, ale żaden element nie pozwolił jej dokładnie przewidzieć, która metoda powinna zostać wywołana. Metoda branch_escape_filter można porównać do pełnomocnika. To w tej metodzie określimy, w jaki sposób uzyskujemy dostęp do atrybutu.

Wnioski

Chociaż szablony twig są automatycznie buforowane przez Symfony, przechowywana jest tylko wersja PHP, ale bez interpretacji tego, co chcesz pobrać. Teoretycznie istnieje zatem sposób na optymalizację połączeń i czasu generowania naszych szablonów, ponieważ weryfikacja przeprowadzana jest przy każdym połączeniu.

Benchmark

Nadal chciałem mieć pojęcie o korzyściach, jakie można uzyskać, wywołując metody zamiast „ alias ".

W pierwszym przypadku wywołuję szablon, który wywoła 10 razy ten sam obiekt, który z kolei wywoła 25 aliasów. To oznacza 250 połączeń. Wyniki są powiększane przez pętlę 10, aby umożliwić dokładne obliczenia przyrostu wydajności.

Po drugie, wywołuję szablon, który wywoła ten sam obiekt 10 razy, a który z kolei wywoła 25 metod (zawsze przez to samo proxy, co dla aliasów). To znowu 250.

Wykonałem połączenie z tymi szablonami 5 razy każdy.

Zauważ, że wszystkie wywołania szablonu wywołujące metody są szybsze. Biorąc średnie, zauważamy, że szablon wykorzystujący aliasy jest dłuższy o 54,6 milisekund (197.4 – 142.8).

Dokonując szybkiego obliczenia zauważamy, że jeśli sprowadzimy to do ogólnego przypadku, szablon wykorzystujący wywołania metod jest szybszy średnio na tych samych danych o około 26.7%. Może to być interesujące podczas wykonywania wielu wywołań obiektów.

Ten drugi artykuł następuje po pierwszym poście, w którym podano szybkie rozwiązania optymalizujące generowanie szablonów. Jest to owoc optymalizacji stosowanej już na stronach w produkcji, które miały zbyt wysoki wskaźnik opóźnień.

Korzystamy ze wszystkich obejmuje de Gałązka zmienić lub uwzględnić nasze poglądy. Ale być może nigdy nie zrozumiałeś, dlaczego mamy możliwość przekazywania parametrów, skoro podstawowe włączenie dziedziczy zmienne z bieżącego kontekstu.

1
{% zawierać „ProjectMyBundle:Sub:template.html.twig” %}

Często używamy tego oznaczenia. W takim przypadku uwzględnienie da kopię wszystkich naszych zmiennych do naszego szablonu. Nie zawsze jest to konieczne i popełniamy błąd kopiując wszystkie nasze zmienne.

Zainteresowanie opcją „tylko”.

Długo zastanawiałem się, jaki jest sens tej opcji. Poza tym trzeba powiedzieć, że dokumentacja nie zawiera zbyt wielu informacji. Możesz rzucić okiem na Twig zawiera dokumentację. Daje niewiele elementów, ale daje szczególnie wadę i brak korzyści: obejście się bez pewnych zmiennych. Widziane w ten sposób, nie jest to opłacalne; dlaczego powinienem obejść się bez niektórych zmiennych.

Zaimplementujmy nasze dodatki! Powiedzmy, że nasz podstawowy szablon ma 5 zmiennych i dołączam szablon, który używa tylko jednej z tych zmiennych, to jest preferowana notacja.

1
{% zawierać „ProjectMyBundle:Sub:template.html.twig” tylko z {„object”: myVar} %}

W ten sposób w moim szablonie będzie dostępna tylko zmienna „obiektowa”. Ogranicza to kopiowanie bezużytecznych zmiennych, a tym samym alokację pamięci (oszczędność czasu i zużycia pamięci).

Kod i przypadki użycia

1
2
3
4
5
6
// Kontroler
// Tutaj generuje szablon, przekazując imponującą zmienną (kolekcję) zawierającą wszystkie obiekty dla danej tabeli
publiczny funkcjonować testAkcja() {
$obiekty = $ to->kontener->pobierz(„doctrine.orm.default_entity_manager”)->pobierzRepozytorium(„ProjectMyBundle:Test”)->znajdź wszystko();
powrót szyk("rzeczy" => $obiekty);
}

Zapętlamy naszą kolekcję i przekazujemy szablon każdej iteracji kolekcji do szablonu. W tym przypadku za każdym razem, gdy wzywamy do integracji szablonu, kopiowane są wszystkie zmienne, a także te, które zostały przekazane opcję „z”.. W naszym pierwszym przypadku moglibyśmy sobie wyobrazić dostęp do naszej kolekcji (obiektów) oraz naszej bieżącej iteracji (obiekt).

1
2
3
4
5
{#Szablon 1#}
{% dla obiekt w obiektach %}
{% zawierać "ProjectMyBundle:Sub:template.html.twig" z {"object": obiekt} %}
{% koniec za %}

W naszym drugim przypadku aktywuję opcję tylko co pozwala kopiować tylko zmienne przekazane jako parametry. Łatwy ?

1
2
3
4
5
{#Szablon 2#}
{% dla obiekt w obiektach %}
{% zawierać „ProjectMyBundle:Sub:template.html.twig” tylko z {„object”: obiekt} %}
{% koniec za %}

Benchmark

Testy przeprowadziłem na szablonach i kodzie podanym w części powyżej. Wykonałem 5 iteracji każdego szablonu, pamiętając o opróżnieniu pamięci podręcznej przed każdym pierwszym testem.

Na tym wykresie widzimy, że ładowanie jest generalnie dłuższe dla tych, którzy nie korzystają z tej opcji tylko. Różnica ma tendencję do zmniejszania się po buforowaniu. Wynika to z faktu, że mój szablon jest mały i wykorzystuje niewiele zmiennych. W bardziej stosowanych przypadkach zyski sięgają nawet 30%.

Tutaj, jeśli uśrednimy wartości, uzyskamy średnią różnicę 9 ms (48,6 – 39,6 = 9). Możemy zatem obliczyć przybliżony zysk w wysokości 20%, nawet jeśli w naszym przypadku ma to być postrzegane z perspektywy, ponieważ pierwszy strzał jest strasznie długi bez użycia „ tylko ".

★ ★ ★ ★ ★