Symfony Flex a novinky v Symfony 4

Symfony Flex je nový způsob konfigurace knihoven pro Symfony aplikace. Pro správu závislostí se stále používá Composer, ale Flex navrch přidává automatickou konfiguraci balíčků. V článku si ukážeme, jak to funguje.

Pokud jste dříve instalovali Bundle do Symfony aplikace, bylo ho kromě instalace přes Composer potřeba také ručně zaregistrovat v AppKernel, zkopírovat konfiguraci do config.yml, nastavit parametry v parameters.yml, vytvořit prázdné adresáře pro cache, přidat je do .gitignore apod. Symfony Flex je plugin do Composeru, který ve chvíli, kdy nainstalujete nový balíček, vyřídí i všechnu tuhle administrativu.

Symfony je nově mikroframework

I přesto, že bylo možné ze Symfony používat jen jednotlivé komponenty, typická Symfony aplikace měla všechny komponenty nainstalované od začátku skrz balíček symfony/symfony.

Díky snadné instalaci a hlavně konfiguraci jednotlivých komponent je Symfony nově v základní instalaci mikroframework, do kterého si doplníte potřebné moduly. Pokud jste dříve nainstalovali Symfony, měli jste rovnou k dispozici komponenty jako Twig nebo formuláře. Což je super, pokud vytváříte běžnou webovou aplikaci, ale zbytečné pro API nebo konzolovou aplikaci.

Dříve se pro vytvoření kostry aplikace doporučoval samostatný konzolový nástroj symfony, teď už se na to používá přímo Composer. Pomocí následujícího příkladu vytvoříte kostru projektu založenou na symfony/skeleton v adresáři symfony-pokus.

composer create-project symfony/skeleton symfony-pokus

Získáte tím opravdu jen holou kostru aplikace, takže pokud víte, že bude vytvářet běžnou webovou aplikaci, je vhodnější použít symfony/website-skeleton, který vytvoří aplikaci podobnou „Symfony Standard Edition“ (tzn. to, s čím se začínalo dříve).

Nová adresářová struktura

Symfony 4 používá novou adresářovou strukturu. Změna měly dva důvody – zaprvé vůbec umožnit fungování Symfony Flex, a pak také se zbavit některých věcí, které byly zbytečně odlišné od zbytku ekosystému.

Nová adresářová struktura vypadá následovně:

symfony-pokus/
├─ bin/
│  └─ console
├─ config/
├─ public/
│  └─ index.php
├─ src/
│  └─ Kernel.php
├─ var/
│  ├─ cache/
│  └─ log/
└─ vendor/
  • Adresář web je nově přejmenovaný na public a místo app.php a app_dev.php je v něm jen index.php
  • Všechen PHP kód je v adresáři src
  • AppKernel.php se přesunul z adresáře app do src a nově se jmenuje jen Kernel.php
  • var je určený na různé cache a logy a je postradatelný (potřebné podadresáře se vytvoří automaticky), nově je v .gitignore
  • Adresář config se z app přesunul přímo do rootu projektu. Místo jednoho velkého config.yml se pro konfiguraci knihoven používají samostatné soubory v config/packages/ (třeba doctrine.yaml nebo twig.yaml)
  • Rozdělování aplikace do bundlů už není doporučený postup (ono to stejně moc nedávalo smysl), takže namespace tříd v src už začíná přímo na App\

Dotenv a .env místo parameters.yml

Jedním z principů tzn. Twelve-Factor App je umístění konfiguračních hodnot odlišných pro jednotlivá prostředí (local, dev, staging, produkce) mimo aplikační kód, do proměnných prostředí (environment variables, env vars, env).

Symfony se toho nově drží také, doporučený postup je pro konfiguraci odlišnou v jednotlivých prostředích používat environment variables. Protože ne vždy je vhodné a možné používat proměnné prostředí přímo, lze konfiguraci umístit i do souboru .env a Symfony ji bude automaticky používat (pokud v opravdových proměnných prostředí nebude nastavená hodnota APP_ENV). O načítání proměnných prostředí se v Symfony stará komponenta Dotenv.

Soubor .env se neverzuje a je nutné ho vytvořit a hlavně naplnit konfigurací v každém prostředí zvlášť. Kromě něj existuje i .env.dist, který obsahuje seznam všech konfiguračních parametrů a jejich výchozí hodnoty. Zjednodušeně lze říci, že .env a .env.dist nahrazují parameters.yml a parameters.yml.dist.

Užitečnou vlastností je, že .env soubor má standardní formát, takže hodnoty v něm lze využít třeba i pro konfiguraci Dockeru.

Novinkou je, že místo jednotlivých hodnot (username, password, host apod.) se pro konfiguraci databáze, Swiftmaileru a možná i dalších používá formát připomínající URL:

# ukázka souboru .env
DATABASE_URL="mysql://db_user:db_password@127.0.0.1:3306/db_name"

Dejte si pozor na escapování, sám jsem se na to nachytal. Pokud budete mít například v hesle do databáze $, je potřeba ho buď oescapovat a nebo celou URL dát do apostrofů ' místo uvozovek " (chová se to trochu podobně jako stringy v PHP).

Ukázka fungování Symfony Flex

Poznámka: Symfony Flex nemá kromě jména nic společného s Adobe Flex.

Navážu na ukázku ze začátku článku, kdy jsme vytvořili kostru aplikace založenou na symfony/skeleton. Pokud se teď do aplikace rozhodneme nainstalovat Twig, tak se k němu chováme jako k běžnému Composer balíčku:

λ composer require symfony/twig-bundle

./composer.json has been updated

  - Installing twig/twig (v2.4.6): Loading from cache
  - Installing symfony/twig-bridge (v4.0.6): Loading from cache
  - Installing symfony/twig-bundle (v4.0.6): Loading from cache

Symfony operations: 1 recipe (f419b51eb889132a8bb842dc7a3bfe86)
  - Configuring symfony/twig-bundle (>=3.3): From github.com/symfony/recipes:master

Some files may have been created or updated to configure your new packages.
Please review, edit and commit them: these files are yours.

Ve výpise (smazal jsem z něj nepodstatné věci) vidíme, že se nám kromě symfony/twig-bundle nainstaloval i samotný twig/twig a symfony/twig-bridge. To je standardní chování Composeru. Důležité je, že hned pod tím vidíme výpis ze Symfony Flex, který říká, že nám nakonfiguroval symfony/twig-bundle podle receptu z github.com/symfony/recipes.

Co přesně ta konfigurace znamená? Flex udělal následující:

  • v config/bundles.php zaregistroval TwigBundle
  • Vytvořil soubor config/packages/twig.yaml s konfigurací Twigu
  • Vytvořil soubor config/routes/dev/twig.yaml, který registruje routy pro možnost testování designu chybových stránek
  • Vytvořil složku templates a šablonu pro layout templates/base.html.twig
  • Aktualizoval soubor symfony.lock – ten berte podobně jako composer.lock a prostě ho commitujte do gitu

To nám ušetřil docela dost práce, že?

Jak Flex funguje? Není to žádná magie.

Předpokládám, že to vypadalo dost magicky, když se nám při instalaci balíčku najednou něco samo vytvořilo a nakonfigurovalo. V této kapitole vám ukážu, že to není žádná magie a že to je vymyšlené docela chytře.

První otázka, která vás asi napadne je, kde jsme k tomu Flexu vlastně přišli. Je to jednoduché, je to knihovna symfony/flex, která je definovaná jako závislost v composer.json. A není to obyčejná knihovna, je to Composer plugin. To znamená, že může poslouchat na eventách v průběhu toho, kdy Composer instaluje nové balíčky. Takže ve chvíli, kdy nějaký balíček nainstalujete, spustí se Flex a provede jeho konfiguraci. Tím se dostáváme k dalšímu bodu.

To, co má Flex při instalaci balíčku udělat je definované v tzv. receptu, což je JSON soubor ve speciálním formátu. Podívejme se na ten recept, který nám nakonfiguroval Twig:

{
    "bundles": {
        "Symfony\\Bundle\\TwigBundle\\TwigBundle": ["all"]
    },
    "copy-from-recipe": {
        "config/": "%CONFIG_DIR%/",
        "templates/": "templates/"
    },
    "aliases": ["twig", "template", "templates"]
}

V bundles je definované, jak se má daný bundle zaregistrovat. Mnohem zajímavější je sekce copy-from-recipe, která určuje, které soubory z receptu se mají nakopírovat do projektu. V případě toho Twigu to je config a templates. Opět si je můžete prohlédnout na Githubu. V tomto receptu už je jen jedna další sekce, a to aliases. Je to specialita, kdy některé oficiální knihovny můžete nainstalovat i pomocí toho zkráceného aliasu. Takže by nám předtím místo composer require symfony/twig-bundle stačilo zavolat jen composer require twig. Osobně mi to přijde spíš jako nesmysl, kdy zavolám composer install mail a budu doufat, že se mi nainstaluje něco rozumného (ale pro začátečníky, kteří nechtějí zkoumat a porovnávat balíčky, to může být užitečné). Recepty mohou dělat i další věci – třeba přidávat proměnné do .env.dist nebo přidávat soubory do .gitignore.

A jak ty recepty vznikají? Symfony spravuje dva repositáře, symfony/recipes pro oficiální vyladěné recepty a symfony/recipes-contrib pro komunitní recepty. Nevýhodou je, že nelze snadno spustit vlastní repositář s recepty (ať už veřejný nebo privátní), ani umístit recept přímo k samotnému projektu. Pokud máte čas, můžete si k tomu pročíst dlouhou a výživnou diskuzi. Ale na druhou stranu, není tak těžké doplnit chybějící recept do recipes-contrib.

Na receptech je nejlepší to, že pro populární a často používané balíčky už jsou hotové, takže se o to nemusíte starat a jen je používáte.

Novinky v Symfony 4

Původně jsem plánoval dva samostatné články, jeden o Flexu a jeden o novinkách v Symfony 4. Ale vzhledem k tomu, jak moc to spolu souvisí, jsem se rozhodl to nechat v jednom.

Flex jako hlavní novinku jsem rozebral výše. Zajímavostí je, že původně měl být jen pro Symfony 4.0 a PHP 7.1, ale nakonec ho upravili i pro Symfony 3.3+ a PHP 7.0+. Takže ho můžete snadněji začít používat i na starším projektu. Nicméně nové projekty dneska už nedává smysl dělat na něčem jiném než Symfony 4.0 a PHP 7.2 (v nejhorším ještě na PHP 7.1).

Webpack Encore je JavaScriptová (!) knihovna pro snadnější konfiguraci Webpacku pro Symfony aplikaci. Umí kompilovat Less, minifikovat JS apod. Zkompilovaným souborům dává do názvu hash a generuje manifest.json, který lze pak snadno použít v Twigu ({{ asset('/css/app.css') }} vypíše něco jako /build/css/app.b916426ea1d10021f3f17ce8031f93c2.css). Prostě dneska už je Assetic out, a Webpack Encore in.

MakerBundle je knihovna na generování různých prázdných komponent v Symfony – commandů, controllerů, validátorů nebo třeba Twig extensions.

Chytrý autowiring. Díky vylepšením DI už typicky není potřeba nic moc přidávat do services.yaml, jen pokud budete mít nějakou specialitku nebo budete potřebovat autowirovat skalární parametry.

Rychlost. Symfony 4 by měla být rychlejší než předchozí verze. Jednak díky různým optimalizacím a také kvůli tomu, že jsou odebrané věci, které byly v 3.4 deprecated, takže je tam méně kódu starajícího se o zpětnou kompatibilitu.

Upgrade na Symfony 4 a Flex

Symfony 4.0 podporuje PHP 7.1 a novější, takže pokud jste ještě z nějakého důvodu na PHP 7.0, tak musíte přejít na PHP 7.1 a případně rovnou na 7.2.

V Symfony 4.0 nepřibyla žádná funkcionalita oproti verzi 3.4 (byly vydané najednou), ale byly odebrány věci, které byly v 3.4 označené jako deprecated. Takže prvním krokem by měl být upgrade na Symfony 3.4 a vyřešení všech deprecated varování. Následný upgrade na 4.0 by už měl být snadný.

Teprve po upgrade na 4.0 bych se začal zabývat přechodem na Symfony Flex (určitě to řešte zvlášť, nebo se z toho zblázníte). Upgrade na Flex je hezky popsaný v dokumentaci. Důležité je, že by aplikace už neměla záviset na balíčku symfony/symfony, ale přímo na jednotlivých komponentách, které opravdu potřebuje. To je koneckonců dobrý nápad i bez Flexu.

Ještě, než článek uzavřu, tak tu zdůrazním, že Flex je i v Symfony 4 volitelný, takže pokud upgradujete existující aplikaci, tak se s ním vůbec nemusíte zabývat. Všechno bude stále fungovat, jen si neušetříte práci s konfigurací nových knihoven.

Závěrem

Symfony Flex a Symfony 4 přinášejí nový způsob budování aplikace, kdy nově začínáte s prázdnou aplikací a postupně instalujete jen ty knihovny, které jsou pro konkrétní aplikaci opravdu potřeba. Aby to nebylo spoustu manuální práce s konfigurací, vznikl koncept receptů, které umožňují automatizovat konfiguraci jednotlivých knihoven. A kupodivu to funguje docela pěkně.

Jak se vám Flex líbí? Už jste ho zkoušeli?

Věděli jste, že nám můžete zasílat zprávičky? (Jen pro přihlášené.)

Komentáře: 2

Přehled komentářů

Lukáš Brzák Skvělé!
Tomáš Votruba Dříve anglicky
Zdroj: https://www.zdrojak.cz/?p=21037