Přidej si svou IT školu do profilu a najdi spolužáky zde na síti :)

3. díl - Směrovač (router)

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

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

V minulém dílu našeho seriálu tutoriálů pro jednoduchý objektový redakční systém v PHP 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:

Test routeru v PHP MVC frameworku

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ě si systém zprovozníme.


 

Stáhnout

Staženo 2174x (3.7 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?
23 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 se informační technologie naučil na Unicorn College - prestižní soukromé vysoké škole IT a ekonomie.
Aktivity (1)

 

 

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

Avatar
Bebbana
Člen
Avatar
Bebbana:24.11.2015 19:00

Tak jsem na to přišla, blbě uložený .htdocs, já blbec jsem to měla s příponou .txt a ne bez přípony, takže to apache vubec neviděl. Jen pozor na to pro všechny začátečníky.
Pokud jste to nikdy předtím nevytvářeli tak jako já, tady je návod: http://www.coniseal.com/…amkovy-blok/

 
Odpovědět 24.11.2015 19:00
Avatar
Bita Radek
Člen
Avatar
Bita Radek:22.11.2016 22:05

Vynikající celý seriál ! Moc díky.

 
Odpovědět 22.11.2016 22:05
Avatar
Tomáš Honka:24.12.2016 17:21

Udělal jsem si web, který používá tenhle Směrovač s hezkýma URL. Potřeboval bych ale, aby web fungoval, když hezké URL nefungují a Směrovač tedy dokázal pracovat i s "ošklivými". Nevíte někdo jak na to? Díky moc

 
Odpovědět 24.12.2016 17:21
Avatar
arnost99
Člen
Avatar
Odpovídá na Tomáš Honka
arnost99:22. ledna 10:18

Odkazy zobecníš a naparsuješ přesně, jak je tady v tomto směrovači(samoz­řejmě na základě nějaké obecné definice toho "nehezkýho" URL), akorát musíš dle odlišností "vypodmínkovat"(po­kud chceš použít víc typů URL), aspoň tak bych to řešil já...

 
Odpovědět 22. ledna 10:18
Avatar
arnost99
Člen
Avatar
arnost99:22. ledna 10:22

Můžu poprosit o radu, jak tady z tohoto redakčního systému a (obecně z MVC) nalinkuju metodu třídy (př: z SpravceClanku.php, mam metodu public function ulozClanek($id,$cla­nek){}..) na AJAX tak, abych mohl uložit bez znovunačtení stránky do databáze? Dík

Editováno 22. ledna 10:24
 
Odpovědět 22. ledna 10:22
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na arnost99
David Čápka:22. ledna 10:51

Na kurz navazuje kurz E-shop, kde jsou všechny tyto pokročilé postupy vysvětlené.

Odpovědět 22. ledna 10:51
Miluji svou práci a zdejší komunitu, baví mě se rozvíjet, děkuji každému členovi za to, že zde působí.
Avatar
arnost99
Člen
Avatar
Odpovídá na David Čápka
arnost99:22. ledna 11:42

Díky, ten si klidně taky projdu, ale v této chvíli bych raději ocenil konkrétní radu a ne odkaz na zdroj :-) .Díky

 
Odpovědět 22. ledna 11:42
Avatar
DREAMDEV
Člen
Avatar
DREAMDEV:13. března 13:39

zdravim trochu som vylepsil tento MVC system ale mam tam jednu taku zahadu. Spravil som si funkciu na zasielanie emailov ak nahodov nastane na webe nejaka chyba. Obcas mi pride mail ktory hlasi ze v routri vo funkcii parseURL je chyba:

Error message: Undefined index: path
Error location: Router.php Ln: 43

coz mi pride ako keby $_SERVER['REQU­EST_URI'] nebolo nastavene moze sa stat ze by to nejako spustali roboti a preto REQUEST_URI nie je nastavene? alebo ako sa moze stat ze REQUEST_URI nie je nastavene?

 
Odpovědět 13. března 13:39
Avatar
Daniel Horák:2. června 5:56

Parádní tutoriál, díky!

 
Odpovědět 2. června 5:56
Avatar
Jan Bartík
Člen
Avatar
Jan Bartík:12. srpna 10:33

Mazec seriál na pochopení OOP v praxi . Aspoň teda doufám že tomu začínám rozumět :) . Vše funguje, tk doufám že to tak pujde i dál ...

Odpovědět 12. srpna 10:33
Janko
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 74. Zobrazit vše