Symfony po krůčkách – Routing

Hezké URL jsou ve světě webových aplikací v dnešní době již v podstatě nutností. Dnešní díl přivádí pod světla ramp Symfony komponentu Routing, díky které je práce s hezkými URL a jejich správa opravdu jednoduchá a elegantní. Dnes si ukážeme základní principy routování v Symfony.

Seriál: Symfony po krůčkách (18 dílů)

  1. Symfony po krůčkách – Event Dispatcher 30.11.2015
  2. Symfony Console jako první rande se Symfony 7.12.2015
  3. Symfony po krůčkách – Filesystem a Finder 14.12.2015
  4. Symfony po krůčkách – Paralýza možností? OptionsResolver tě zachrání 21.12.2015
  5. Symfony po krůčkách – spouštíme procesy 4.1.2016
  6. Symfony po krůčkách – Translation – překlady jednoduše 11.1.2016
  7. Symfony po krůčkách – Validator (1) 18.1.2016
  8. Symfony po krůčkách – Validator (2) 25.1.2016
  9. Symfony po krůčkách – Routing 1.2.2016
  10. Symfony po krůčkách – MicroKernel 9.2.2016
  11. Konfigurujeme Symfony pomocí YAMLu 16.2.2016
  12. Symfony po krůčkách – oblékáme MicroKernel 23.2.2016
  13. Symfony po krůčkách – ClassLoader 29.2.2016
  14. Symfony po krůčkách – Twig 8.3.2016
  15. Symfony po krůčkách – Twig II. 15.3.2016
  16. Symfony po krůčkách – DomCrawler a CssSelector 23.3.2016
  17. Symfony po krůčkách – HTTP fundamentalista 12.4.2016
  18. Symfony po krůčkách – ušli jsme pořádný kus 19.4.2016

Routing nám slouží ke 2 základním úkolům:

  1. Na URL namapuje pojmenovanou sadu konfiguračních parametrů (tzv. routa), podle kterých může aplikace provést konkrétní akce. (Např. 'marketing/article/new' => 'article_new').
  2. Na základě routy generuje URL. (Tzn. opačný směr 'article_new' => 'marketing/article/new').

Příklad na začátek

Komponentu lze nainstalovat pomocí Composeru:

composer require symfony/routing

Pro úplný základ routování jsou potřeba 3 části:

  1. RouteCollection – obsahuje kolekci rout (routa je představována třídou Route).
  2. RequestContext – obsahuje informace o aktuálním requestu.
  3. UrlMatcher – provádí mapování requestu na konkrétní routu.

Jak spolu jednotlivé části fungují, lze vidět na jednoduchém příkladu:

use Symfony\Component\Routing\Matcher\UrlMatcher;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;

require_once __DIR__ . '/vendor/autoload.php';

$route = new Route('/hello', ['controller' => 'GreetingController']); 

$routeCollection = new RouteCollection();
$routeCollection->add('greeting', $route);

$requestContext = new RequestContext('/');

$urlMatcher = new UrlMatcher($routeCollection, $requestContext);

$parameters = $urlMatcher->match('/hello');
var_dump($parameters);
// ['controller' => 'GreetingController', '_route' => 'greeting']

Stačí nám 3 důležité třídy

Route – co kam vede

Třída Route přebírá jako první parametr v konstruktoru textový řetězec obsahující část URL za doménou, tzv. URL path. Jako druhý parametr se předává pole proměnných, které může obsahovat cokoliv, co logika vaší aplikace vyžaduje ke zpracování požadavku. Zde je kupříkladu definován kontrolér, protože Symfony stojí na MVC architektuře a aplikace potřebuje vědět, který kontrolér se má o požadavek postarat.

RouteCollection – když je jich víc

Pomocí metody RouteCollection::add() lze do kolekce přidávat libovolné množství rout. Metoda má dva argumenty, první je název routy, druhý je instance třídy Route.

UrlMatcher – volba té pravé

Metoda UrlMatcher:match() pak hledá routu na základě URL a pokud takovou nalezne, vrací pole parametrů dané routy rozšířené o její název pod klíčem _route. Pokud není nalezena žádná odpovídající routa, je vyhozena výjimka ResourceNotFoundException a my můžeme uživateli vrátit například 404 stránku.

Vytváříme Routu

Nejčastěji budete pravděpodobně využívat první 2 argumenty konstruktoru:

  • na prvním místě URL path, která může obsahovat placeholdery pro dynamickou část tvořenou parametry routy (např. article/edit/{articleId})
  • na druhém místě se pak nastavuje pole výchozích hodnot, které je vráceno v případě, že request odpovídá dané routě

$route = new Route('/hello', ['controller' => 'GreetingController']);

Zajímavý je poslední parametr $condition – podmínka, která musí být vyhodnocena jako pravdivá, aby byla routa rozpoznána. K čemu slouží ostatní parametry, lze nastudovat v dokumentaci.

Vytváříme RequestContext

RequestContext má v sobě informace o aktuálním requestu, které můžeme definovat pomocí parametrů konstruktoru. Všechny potřebné údaje lze získat z globální proměnné $_SERVER, ale elegantnějším řešením je použití Symfony komponenty HttpFoundation a její třídy Request. RequestContext pak vytvoříme následujícím způsobem:

use Symfony\Component\HttpFoundation\Request;   

$context = new RequestContext(); 
$context->fromRequest(Request::createFromGlobals());

Generujeme URL

Symfony poskytuje jednoduchý nástroj pro generování URL pro danou routu, a tím je třída UrlGenerator. Jeho použití je opravdu přímočaré:

use Symfony\Component\Routing\Generator\UrlGenerator;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;

require_once __DIR__ . '/vendor/autoload.php';

$routes = new RouteCollection();
$routes->add('article_edit', new Route('/article/edit/{articleId}'));

$context = new RequestContext('/');

$generator = new UrlGenerator($routes, $context);

$url = $generator->generate('article_edit', ['articleId' => 1]);
var_dump($url);
// /article/edit/1

Metoda UrlGenerator::generate() přebírá:

  • 1. parametr název routy,
  • na 2. místě pole parametrů
  • a 3. parametrem si můžeme určit, zda chceme generovat cestu absolutní nebo relativní.

Další způsoby definování rout

Už jsme si ukázali, že routy do kolekce můžeme přidávat pomocí metody RouteCollection::add(). To ale rozhodně není jediný způsob. Podívejme se na další možnosti, jak definovat routy v naší aplikaci:

  • Definice v souboru – routy můžeme definovat v konfiguračních yml nebo xml souborech. Definice routy v yml může vypadat např. takto:
# routes.yml
article_edit:
path: /article/edit/{articleId}
defaults: { _controller: ArticleController::editAction }
requirements:
    articleId: \d+

Pro načtení definice využijeme YamlFileLoader. Aby tento příklad fungoval, je potřeba mít nainstalované Symfony komponenty Config a Yaml (composer require symfony/config symfony/yaml).

use Symfony\Component\Config\FileLocator;
use Symfony\Component\Routing\Loader\YamlFileLoader;

require_once __DIR__ . '/vendor/autoload.php';

$locator = new FileLocator(__DIR__);
$loader = new YamlFileLoader($locator);
$routeCollection = $loader->load('routes.yml');

Jak to vše poskládat dohromady?

Jednoduše! Součástí Routing komponenty je třída Router, která vše zaobaluje a představuje tak krásný příklad integrace jednotlivých částí routovacího systému v Symfony.

use Symfony\Component\Config\FileLocator;
use Symfony\Component\Routing\Loader\YamlFileLoader;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\Router;

require_once __DIR__ . '/vendor/autoload.php';

$locator = new FileLocator(__DIR__);
$requestContext = new RequestContext();

$router = new Router(
    new YamlFileLoader($locator),
   'routes.yml',
   [],
   $requestContext
);
$route = $router->match('/article/edit/1');
var_dump($route);
// ['_controller' => 'ArticleController::editAction', 'articleId' => '1', '_route' => 'article_edit']

$url = $router->generate('article_edit', ['articleId' => 1]);
var_dump($url);
// '/article/edit/1'

Zase o krok dále

Dnes jsme si ukázali:

  • co je to routa,
  • k čemu slouží routování a jak to v Symfony funguje,
  • jak generovat URL adresy,
  • jakými způsoby lze definovat routy v aplikaci.

Vystudoval jsem softwarové inženýrství na FEI v Ostravě a od září 2014 pracuji v ShopSys jako vývojář nové e-commerce platformy postavené na Symfony frameworku.

Komentáře: 3

Přehled komentářů

lenoch
Dennis Fridrich Re:
lenoch Re:
Zdroj: https://www.zdrojak.cz/?p=17205