Akce! Dobij si body, napiš nám do zpráv "Přes léto se to naučím!" a dobijeme ti ještě navíc 50% z této částky! Sleva na výuku platí do 22.6.2018.

Lekce 3 - Směrovač (router)

PHP MVC Směrovač (router) American English version English version

ONEbit hosting Unicorn College Tento obsah je dostupný zdarma v rámci projektu IT lidem. Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V minulé lekci, .htaccess, autoloader a obecný kontroler, jsme si nastavili .htaccess, vytvořili index.php a obecný kontroler. Dnes se budeme věnovat směrovači, tedy komponentě, která podle URL adresy nasměruje požadavek na správný kontroler.

Směrovač

Směrovač (anglicky router) dostane URL adresu, kterou si zpracuje a na jejím základě zavolá příslušný kontroler. Opět je několik způsobů, kterými lze směrovač implementovat a opět jsem vybral ten nejjednodušší. Princip směrovače nápadně připomíná princip kontroleru, toho také využijeme, směrovač bude kontroler.

Směrovač tedy přidáme jako kontroler. Ve složce kontrolery vytvoříme soubor SmerovacKontro­ler.php a do něj stejnojmennou třídu, která bude dědit z obecného Kontroleru, který jsme si udělali minule. Nezapomeneme implementovat abstraktní metodu zpracuj().

Směrovač dle adresy zjistí, který kontroler voláme, vytvoří nám ho a zároveň i uloží do atributu $kontroler, který třídě rovněž přidáme.

<?php

class SmerovacKontroler extends Kontroler
{

        protected $kontroler;

        public function zpracuj($parametry)
        {
        }

}

Možná je trochu matoucí, že v sobě máme vlastně vložené 2 kontrolery, ale je to tak. Kontroler SmerovacKontroler bere URL od uživatele, tu zpracuje a podle ní zavolá příslušný vložený kontroler (např. ClanekKontroler). Oba kontrolery budou mít pohled, Smerovac bude mít šablonu s rozložením stránky (hlavička, menu atd.) a vložený kontroler bude mít šablonu s obsahem dané stránky (článek, kontaktní formulář, přihlašovací obrazovka atd.).

Parsování URL adresy

Jako první si naparsujeme URL adresu a to přímo v PHP. Adresa nám přijde jako textový řetězec, bude vypadat stejně, jako ta v adresním řádku. Pojďme se dohodnout nejprve na jejím formátu, který bude následující a který jsme již minule naťukli:

http://www.domena.cz/kontroler/parametr2/parametr3

V praxi by vypadala třeba takto:

http://www.domena.cz/clanek/nazev-clanku

Říkáme, že voláme kontroler ClanekKontroler a předáváme mu parametr "nazev-clanku". Kontroler si už článek vezme od modelu a předá ho pohledu, který ho vypíše uživateli.

Např. z této URL:

http://www.domena.cz/kontroler/parametr2/parametr3

bychom potřebovali získat takového pole:

Array
(
    [0] => kontroler
    [1] => parametr2
    [2] => parametr3
)

Přijdeme třídě tedy metodu parsujURL():

private function parsujURL($url)
{

}

K naparsování url adresy nám PHP poskytuje funkci parse_url(), která za nás sice neudělá všechnu práci, ale pomůže nám oddělit část s protokolem a doménou od části s parametry. Funkce vrátí asociativní pole, část "/kontroler/pa­rametr2/parame­tr3" dostaneme pod indexem "path". Pozor si dáme jen na "/", kterým může tato část začínat, pokud tam je, jednoduše ho odstraníme pomocí funkce ltrim(). Odstraníme také bílé znaky kolem URL (kdyby za ni třeba někdo napsal mezeru), k tomu slouží PHP funkce trim().

$naparsovanaURL = parse_url($url);
$naparsovanaURL["path"] = ltrim($naparsovanaURL["path"], "/");
$naparsovanaURL["path"] = trim($naparsovanaURL["path"]);

Nyní není nic jednoduššího, než si výsledný řetězec rozbít podle lomítek na pole jednotlivých parametrů:

$rozdelenaCesta = explode("/", $naparsovanaURL["path"]);

Výsledek vrátíme a funkce k parsování URL je hotová:

return $rozdelenaCesta;

Volání vloženého kontroleru

Přesuňme se do metody zpracuj(), která se nám na začátku požadavku zavolá. V argumentu $parametry budeme očekávat pole, kde na 1. indexu bude URL adresa. Tu si naparsujeme pomocí naší metody:

$naparsovanaURL = $this->parsujURL($parametry[0]);

Zatím nebudeme ošetřovat případy, kdy je URL zadána nekompletní nebo neexistující.

Získání názvu třídy

První úkol bude zjistit jméno třídy kontroleru. Již víme, že název kontroleru je 1. parametr v naparsované URL adrese. Pro URL adresy však platí jiné konvence, než pro názvy tříd. Proto nám název kontroleru přijde jako "nazev-kontroleru" a my z něj potřebujeme vytvořit "NazevKontrole­ruKontroler", tedy např. řetězec "clanek" převedeme na "ClanekKontroler" a "vypis-uzivatelu" na "VypisUzivate­luKontroler". Na tento převod si opět vytvoříme ve třídě metodu, bude se jmenovat pomlckyDoVelblou­diNotace();

private function pomlckyDoVelbloudiNotace($text)
{

}

Použijeme PHP funkci ucwords(), která zvětší počáteční písmeno všech slov ve větě. Funkce sice není UTF-safe, ale to nám zde nevadí. Z parametru si tedy nejprve uděláme větu a to jednoduše tak, že pomlčky nahradíme mezerami:

$veta = str_replace('-', ' ', $text)

Následně zvětšíme první písmena slov a mezery odstraníme:

$veta = ucwords($veta);
$veta = str_replace(' ', '', $veta);

To je vše. Kód by šel napsat i do jednoho řádku, ale pro potřeby tutoriálu jsem ho rozepsal. Metoda převede např. řetězec "vypis-uzivatelu" na VypisUzivatelu. Výsledek navrátíme:

return $veta;

Vraťme se do metody zpracuj() a zjistěme si název třídy kontroleru pomocí naší nové metody:

$tridaKontroleru = $this->pomlckyDoVelbloudiNotace(array_shift($naparsovanaURL)) . 'Kontroler';

Pomocí array_shift() jsme získali 1. parametr z naparsované URL a zároveň ho z tohoto pole i odstranili, již ho tam totiž nebudeme potřebovat.

Název třídy kontroleru si pro testovací účely pouze vypišme:

echo($tridaKontroleru);

Stejně tak si vypišme i zbytek pole z URL adresy:

echo('<br />');
print_r($naparsovanaURL);

Volání směrovače

Přesuňme se do index.php a vytvořme si zde směrovač. Necháme ho zpracovat URL adresu, kterou v PHP nalezneme v superglobálním poli $_SERVER pod klíčem REQUEST_URI. Hodnotu ještě musíme vložit do pole, jelikož to metoda zpracuj() očekává:

$smerovac = new SmerovacKontroler();
$smerovac->zpracuj(array($_SERVER['REQUEST_URI']));

Díky autoloaderu zminula se nám třída SmerovacKontroler sama načte. Celou magii si vyzkoušíme, zadáme následující URL:

localhost/clanek/nazev-clanku/dalsi-parametr

A měli bychom dosáhnout následujícího výsledku:

Your page
localhost/cla­nek/nazev-clanku/dalsi-parametr

Směrovač nám tedy funguje, z URL adresy nám zjistil název kontroleru a pole parametrů. Pro dnešek toho již bylo dost. Příště, v lekci Propojení kontroleru a pohledu, si systém zprovozníme.


 

Stáhnout

Staženo 2399x (4.21 kB)
Aplikace je včetně zdrojových kódů v jazyce PHP

 

 

Článek pro vás napsal David Čápka
Avatar
Jak se ti líbí článek?
25 hlasů
Autor pracuje jako softwarový architekt a pedagog na projektu ITnetwork.cz (a jeho zahraničních verzích). Velmi si váží svobody podnikání v naší zemi a věří, že když se člověk neštítí práce, tak dokáže úplně cokoli.
Unicorn College Autor sítě se informační technologie naučil na Unicorn College - prestižní soukromé vysoké škole IT a ekonomie.
Aktivity (6)

 

 

Komentáře
Zobrazit starší komentáře (77)

Avatar
Lukáš Hornych
Redaktor
Avatar
Lukáš Hornych:24.10.2017 14:56

To bys sice mohl posílat jako string, ale musel bys to v každém dalším kontroleru zbytečně pořád dokola parsovat. Nemyslíš, že je proto lepší to předat jako pole jen tomu prvnímu, který si to naparsuje a pošle to ostatním kontrolerům jako pole parametrů a ty pak s těmi parametry můžeš pohodlně pracovat jako s polem? ;-)

 
Odpovědět 24.10.2017 14:56
Avatar
Odpovídá na Lukáš Hornych
radovan.skvor:24.10.2017 15:19

Teď tě vůbec nechápu.
Pokud budu metodě zpracuj předávat adresu stringem v poli nebo pouze stringem není v tom přeci rozdíl, aplikace bude fungovat pořád stejně.

 
Odpovědět 24.10.2017 15:19
Avatar
Lukáš Hornych
Redaktor
Avatar
Odpovídá na radovan.skvor
Lukáš Hornych:24.10.2017 15:33

No tak přece když budeš předávat adresu stringem, tak v každém novém kontroleru si ji budeš muset rozkouskovat na jednotlivé parametry. Kdežto takhle ti to udělá ten první router a potom se o to už nemusíš starat.

 
Odpovědět 24.10.2017 15:33
Avatar
Odpovídá na Lukáš Hornych
radovan.skvor:24.10.2017 15:39

No dojedu tutoriál do konce a pak mě to snad bude jasný asi tomu ještě pořád tomu MVC, děkuju za tvůj čas :-)

 
Odpovědět 24.10.2017 15:39
Avatar
Odpovídá na Lukáš Hornych
radovan.skvor:25.10.2017 7:51

V další kapitole jsem to pochopil ;-)

 
Odpovědět  +1 25.10.2017 7:51
Avatar
box.me
Člen
Avatar
box.me:17. února 9:22

Narazil jsem na problém při testování na localu. Nefungoval mi rewrite. Většina zde asi má zkušenosti s konfigurací apache na to aby fungoval .htaccess. Pro ty kdo by ho museli konfigurovat od začátku:

v souboru httpd.conf:
možnost AllowOverride All (pokud je none - .htaccess nemá vliv)
odkomentovat řádek - LoadModule rewrite_module modules/mod_rew­rite.so

 
Odpovědět 17. února 9:22
Avatar
radian1
Člen
Avatar
radian1:12. března 20:43

ahoj, když napíšu tuhle url adresu

http://www.domena.cz/clanek/nazev-clanku

jak ji skript může získat? A dá se nějak záskat i hash (např. #obrazek12)?
Koukam jsem se do proměnné $_SERVER a tam to nikde neni, a neni tam ani úplně celá adresa, jenom REQUEST_SCHEME, REQUEST_URI, a další z kterých bych to mohl poskládat....

 
Odpovědět 12. března 20:43
Avatar
Odpovídá na radian1
Michal Šmahel:13. března 12:14

Ahoj, pokud chceš celý tvar URL, musíš si ho poskládat z částí superglobálního pole $_SERVER.

Co se týče kotvy (#) a údajů za ní, ty náleží pouze klientské části (pro nasměrování na určitý bod a pro Javascript). Zatím jsem neviděl žádné rozumné řešení, jedině snad použít k odeslaní Javascriptu.

Pokud se tu najde někdo, kdo toho využívá a našel nějaké dobré řešení, budu rád, když mě doplní.

Odpovědět 13. března 12:14
Nejdůležitější je motivace, ovšem musí být doprovázena činy.
Avatar
radian1
Člen
Avatar
Odpovídá na Michal Šmahel
radian1:13. března 19:54

hm, takže nejdříve musím složit url a potom ji zas rozbít pres parse_url? OK

 
Odpovědět 13. března 19:54
Avatar
Odpovídá na radian1
Michal Šmahel:13. března 20:26

Jde o to, co potřebuješ. Pokud řešíš zpracování URL parametrů nějakým parserem v MVC, stačí ti hodnota na klíčí REQUEST_URI.

...

$params = $_SERVER['REQUEST_URI'];

...
Odpovědět 13. března 20:26
Nejdůležitější je motivace, ovšem musí být doprovázena činy.
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 87. Zobrazit vše