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 2250x (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 (72)

Avatar
Daniel Horák:2.6.2017 5:56

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

 
Odpovědět 2.6.2017 5:56
Avatar
Jan Bartík
Člen
Avatar
Jan Bartík:12.8.2017 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.8.2017 10:33
Janko
Avatar
radovan.skvor:24.10.2017 12:40

Ahoj, chci se zeptat z jakého důvodu je u metody zpracuj parametr pole?

 
Odpovědět 24.10.2017 12:40
Avatar
Lukáš Hornych
Redaktor
Avatar
Odpovídá na radovan.skvor
Lukáš Hornych:24.10.2017 13:56

Když v URL adrese budeš mít víc parametrů, tak se ti všechny naskládají do toho pole a ty pak s tím můžeš pracovat dál:

adresa.cz/parameter1/parameter2/parameter3/...
$parametry[0] = "parameter1";
$parametry[1] = "parameter2";
$parametry[2] = "parameter3";
...
 
Odpovědět 24.10.2017 13:56
Avatar
Odpovídá na Lukáš Hornych
radovan.skvor:24.10.2017 14:44

To přeci není pravda, pole v parametru metody zpracuj neobsahuje nic jiného než URL adresu.

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

je to takhle

$parametry[0] = "adresa.cz/parameter1/parameter2/parameter3/...";

teprve až metoda parsujURL rozdělí URL adresu na nazev kontroleru a parametry.

Pokud bych to udělala takto

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

tak by v routeru stačilo toto a nemusel bych předávat URL adresu zbytečně přes pole

public function zpracuj($url)
{
        $naparsovanaURL = $this->parsujURL($url);

napadlo mě ještě že se budou předávat ještě nějaké další parametry které neobsahuje URL adresa ale to jsem si v článcích zadarmo nevšiml.

 
Odpovědět 24.10.2017 14:44
Avatar
Lukáš Hornych
Redaktor
Avatar
Odpovídá na radovan.skvor
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
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 82. Zobrazit vše