DotApp Router
Router je kľúčovou súčasťou DotApp Frameworku, ktorá spravuje routovanie HTTP požiadaviek v aplikácii. Umožňuje vám definovať, ako sa majú požiadavky (napr. GET, POST) mapovať na konkrétne callback funkcie, controllery alebo middleware. Router je navrhnutý tak, aby zvládal statické aj dynamické routy, podporoval hooks (before a after) a poskytoval flexibilitu pri tvorbe webových aplikácií.
1.1 Čo je Router?
Router v DotApp Frameworku je trieda Dotsystems\App\Parts\Router, ktorá spracováva prichádzajúce HTTP požiadavky a smeruje ich na príslušné handlery. Pracuje v súčinnosti s objektom Request, ktorý obsahuje informácie o požiadavke (cesta, metóda, premenné). Jeho hlavnou úlohou je zjednodušiť definovanie rout a zabezpečiť, aby sa pre danú URL a HTTP metódu spustil správny kód.
Router je integrovaný priamo do jadra frameworku, takže ho nemusíte samostatne inštalovať ani konfigurovať – stačí použiť fasádu Router: Router::get(...).
1.2 Kľúčové vlastnosti
Router ponúka širokú škálu funkcií, ktoré uľahčujú vývoj aplikácií:
- Podpora HTTP metód: Definovanie rout pre
GET,POST,PUT,DELETE,PATCH,OPTIONS,HEAD,TRACEa univerzálnu metóduANY. - Dynamické routy: Použitie premenných (napr.
{id}) a regulárnych výrazov na zachytenie častí URL. - Middleware: Podpora
beforeaafterhooks na vykonávanie logiky pred a po hlavnom handleri. - Objekt Request: Prenáša informácie o požiadavke do callbackov a controllerov.
- Flexibilita: Možnosť použiť anonymné funkcie, controllery alebo middleware pomocou reťazca (napr.
"Module:Controller@method!"). - Chaining: Reťazenie metód pre prehľadnejší kód.
1.3 Základné princípy routingu
Router porovnáva aktuálnu URL (získanú z $request->getPath()) a HTTP metódu (z $request->getMethod()) s definovanými routami. Ak sa nájde zhoda:
- Spustia sa prípadné
beforehooks. - Vykoná sa hlavná logika (callback, controller alebo middleware).
- Spustia sa prípadné
afterhooks.
Routy môžu byť:
- Statické: Presná zhoda URL (napr.
/home). - Dynamické: Obsahujú premenné alebo wildcardy (napr.
/user/{id}). - Prvý match víťazí: Použije sa prvá zhodujúca sa routa; ďalšie zhody sa ignorujú.
Router resolvuje požiadavky pomocou metódy resolve(), ktorá sa zvyčajne volá automaticky v rámci životného cyklu DotApp.
Príklad základnej routy:
Routy registrujte v metóde initialize($dotApp) modulu v súbore app/modules/{Module}/module.init.php. Controllery sú v app/modules/{Module}/Controllers/ a volajú sa ako 'Module:Controller@method!'.
// app/modules/HelloWorld/module.init.php → initialize($dotApp)
Router::get('/home', function ($request) {
return "Welcome to the homepage!";
}, Router::STATIC_ROUTE);
Po zadaní URL http://example.com/home sa zobrazí text "Welcome to the homepage!".
2. Začíname
Táto kapitola vás prevedie základmi práce s Routerom v DotApp Frameworku – od inicializácie až po definovanie prvej routy.
2.1 Inicializácia Routeru
Router je služba jadra. Aplikačné routy registrujte cez fasádu Router:: z metódy initialize($dotApp) každého modulu. Controllery sú v app/modules/{Module}/Controllers/.
Technické detaily:
Routerje inštancia triedyDotsystems\App\Parts\Router.- Pri konštrukcii prijíma
$dotAppObj(inštanciu hlavnej triedyDotApp), ktorá mu poskytuje prístup k objektuRequesta ďalším službám frameworku.
2.2 Prístup k Routeru v DotApp
Routy registrujte v module.init.php cez fasádu Router. Objekt $request sa odovzdáva do callbackov a metód controllerov a nesie aktuálnu cestu, metódu a premenné.
Príklad prístupu:
// Check the current path
echo $request->getPath(); // E.g., "/home"
// Check the HTTP method
echo $request->getMethod(); // E.g., "get"
2.3 Definovanie prvej routy
Najjednoduchší spôsob, ako začať s Routerom, je definovať základnú routu pomocou niektorej z HTTP metód (napr. get()). Routa môže byť spojená s anonymnou funkciou (callbackom), controllerom alebo middleware.
Príklad prvej routy s callbackom:
// app/modules/HelloWorld/module.init.php → initialize($dotApp)
Router::get('/home', function ($request) {
return "Welcome to the homepage!";
}, Router::STATIC_ROUTE);
Vysvetlenie:
/home: Statická URL cesta.function($request): Callback, ktorý prijíma objektRequesta vracia odpoveď.- Po zavolaní
http://example.com/homesa zobrazí text "Welcome to the homepage!".
Príklad s controllerom:
Predpokladajme, že máte controller Home v app/modules/HelloWorld/Controllers/Home.php s metódou index:
// app/modules/HelloWorld/Controllers/Home.php
namespace Dotsystems\App\Modules\HelloWorld\Controllers;
class Home extends \Dotsystems\App\Parts\Controller {
public static function index($request) {
return "This is the homepage from the controller!";
}
}
// app/modules/HelloWorld/module.init.php
Router::get('/home', 'HelloWorld:Home@index!', Router::STATIC_ROUTE);
Vysvetlenie:
'HelloWorld:Home@index!': ModulHelloWorld, controllerHome, statická metódaindex. Koncová!vypína DI pre danú metódu.Routerautomaticky načíta a zavolá túto metódu s objektomRequest.
Spustenie routingu:
Framework resolvuje routy po načítaní modulov. Aplikačné routy sa deklarujú v module.init.php.
// app/modules/HelloWorld/module.init.php
public function initialize($dotApp) {
Router::get('/home', function ($request) {
return "Welcome!";
}, Router::STATIC_ROUTE);
}
3. Definovanie rout
Táto kapitola popisuje, ako definovať routy v Routeri DotApp Frameworku. Router podporuje rôzne spôsoby definovania – od základných HTTP metód až po dynamické routy s premennými a prácu s controllermi.
3.1 Základné HTTP metódy (GET, POST, atď.)
Router poskytuje metódy pre všetky štandardné HTTP metódy: get(), post(), put(), delete(), patch(), options(), head() a trace(). Každá metóda definuje routu pre konkrétnu HTTP požiadavku.
Príklad GET routy:
Router::get('/about', function ($request) {
return "This is the About Us page!";
});
Príklad POST routy:
Router::post('/submit', function ($request) {
return "The form has been submitted!";
});
Poznámka: Každá metóda prijíma URL cestu ako prvý parameter a callback (alebo odkaz na controller) ako druhý parameter. Callback vždy dostane objekt $request.
3.2 Metóda match() pre viaceré metódy a URL
Metóda match() umožňuje definovať routu pre viacero HTTP metód naraz alebo pre pole URL adries. Je to flexibilnejší spôsob oproti samostatným metódam ako get() či post().
Príklad s viacerými metódami:
Router::match(['get', 'post'], '/contact', function ($request) {
return "This is the contact page!";
});
Táto routa funguje pre GET aj POST požiadavky na /contact.
Príklad s viacerými URL:
Router::match(['get'], ['/home', '/index'], function ($request) {
return "Welcome to the homepage!";
});
Routa zachytí požiadavky na /home aj /index.
3.3 Statické vs. dynamické routy
Router rozlišuje medzi statickými a dynamickými routami:
- Statické routy: Presná zhoda URL (napr.
/home). - Dynamické routy: Obsahujú premenné alebo wildcardy (napr.
/user/{id}).
Príklad statickej routy:
Router::get('/profile', function ($request) {
return "This is a static profile!";
});
Príklad dynamickej routy:
Router::get('/user/{id}', function ($request) {
return "User profile with ID: " . $request->matchData()['id'];
});
Pri URL /user/123 sa zobrazí "User profile with ID: 123".
3.4 Použitie premenných v routách
Dynamické routy môžu obsahovať premenné označené zloženými zátvorkami (napr. {id}). Tieto premenné sú automaticky extrahované a dostupné cez $request->matchData().
Základné použitie:
Router::get('/article/{slug}', function ($request) {
return "Article: " . $request->matchData()['slug'];
});
Pre /article/how-to-cook sa zobrazí "Article: how-to-cook".
Typované premenné:
Router podporuje aj typovanie premenných:
{param:s}: Reťazec (bez lomítok).{param:i}: Celé číslo.{param:l}: Len písmená.{param:s?}: Voliteľný typovaný parameter (?patrí do zátvoriek).{param*}: Wildcard (zachytí všetko).
Router::get('/user/{id:i}', function ($request) {
return "User ID: " . $request->matchData()['id'];
});
Funguje len pre čísla, napr. /user/123, ale nie /user/abc.
3.5 Práca s controllermi a middleware
Okrem anonymných funkcií môžete routy mapovať na controllery alebo middleware pomocou reťazca v tvare "Module:Controller@method!" alebo "#Module:Middleware@method!".
Príklad s controllerom:
// app/modules/HelloWorld/Controllers/User.php
namespace Dotsystems\App\Modules\HelloWorld\Controllers;
class User extends \Dotsystems\App\Parts\Controller {
public static function show($request) {
return "Displaying the user!";
}
}
// Route definition
Router::get('/user', 'HelloWorld:User@show!');
Príklad s middleware:
// app/modules/HelloWorld/Middleware/AuthMiddleware.php
namespace Dotsystems\App\Modules\HelloWorld\Middleware;
class AuthMiddleware extends \Dotsystems\App\Parts\ModuleMiddleware {
public static function check($request) {
// Return a Response to short-circuit. Returning nothing continues the route.
if (!\Dotsystems\App\Parts\Auth::isLogged()) {
return new \Dotsystems\App\Parts\Response(403, 'Forbidden');
}
}
}
// app/modules/HelloWorld/module.init.php → initialize($dotApp)
Router::get('/secure', 'HelloWorld:User@show!')
->before('#HelloWorld:AuthMiddleware@check!');
Poznámka: Funkcie musia byť definované ako public static a prijímať $request ako parameter. Middleware triedy sa takmer vždy pripájajú cez ->before('#Module:Class@method!'), nie ako hlavný handler routy.
4. Práca s objektom Request
Objekt Request je neoddeliteľnou súčasťou Routera v DotApp Frameworku. Prenáša informácie o aktuálnej HTTP požiadavke a je automaticky odovzdaný do callbackov, controllerov a middleware. Táto kapitola vysvetľuje, ako funguje a ako ho efektívne používať.
4.1 Čo je Request?
Request je inštancia triedy Dotsystems\App\Parts\Request, ktorá slúži ako rozhranie pre prácu s dátami požiadavky. Obsahuje informácie o ceste, HTTP metóde, premenných z dynamických rout a ďalších atribútoch požiadavky. Je automaticky vytvorený pri inicializácii Routera a dostupný cez $request.
Kľúčové vlastnosti:
- Získavanie aktuálnej URL cesty a metódy.
- Prístup k premenným z dynamických rout cez
matchData(). - Prenos dát do callbackov a hooks.
4.2 Prístup k dátam z Requestu
Objekt Request poskytuje metódy na získanie základných informácií o požiadavke:
getPath(): Vráti aktuálnu URL cestu (napr./home).getMethod(): Vráti HTTP metódu (napr.get,post).matchData(): Vráti pole premenných extrahovaných z dynamickej routy.hookData(): Vráti dáta priradené hooks (používa sa pri samostatnýchbefore/after).
Príklad prístupu:
Router::get('/user/{id}', function ($request) {
$path = $request->getPath(); // "/user/123"
$method = $request->getMethod(); // "get"
$id = $request->matchData()['id']; // "123"
return "Path: $path, Method: $method, ID: $id";
});
Pri požiadavke na /user/123 sa zobrazí: "Path: /user/123, Method: get, ID: 123".
4.3 Využitie Requestu v callbackoch
Objekt Request je automaticky odovzdaný ako parameter do všetkých callbackov, controllerov a middleware definovaných v routách. Umožňuje vám pracovať s dátami požiadavky priamo v logike routy.
Príklad s anonymnou funkciou:
Router::get('/profile/{name}', function ($request) {
$name = $request->matchData()['name'];
return "Hello, $name!";
});
Pri /profile/Jano sa zobrazí: "Hello, Jano!".
Príklad s controllerom:
// app/modules/HelloWorld/Controllers/Profile.php
namespace Dotsystems\App\Modules\HelloWorld\Controllers;
class Profile extends \Dotsystems\App\Parts\Controller {
public static function show($request) {
$name = $request->matchData()['name'] ?? '';
return "Profile for: $name";
}
}
// app/modules/HelloWorld/module.init.php → initialize($dotApp)
Router::get('/profile/{name}', 'HelloWorld:Profile@show!');
Výsledok je rovnaký ako pri anonymnej funkcii.
Príklad s middleware:
// app/modules/HelloWorld/Middleware/CheckMiddleware.php
namespace Dotsystems\App\Modules\HelloWorld\Middleware;
class CheckMiddleware extends \Dotsystems\App\Parts\ModuleMiddleware {
public static function verify($request) {
// Optional logging. Do not return a Response unless you want to stop the request.
$path = $request->getPath();
}
}
// app/modules/HelloWorld/module.init.php → initialize($dotApp)
Router::get('/check', 'HelloWorld:User@show!')
->before('#HelloWorld:CheckMiddleware@verify!');
Pri /check sa najskôr spustí middleware. Ak nevráti Response, spustí sa handler User@show!.
Poznámka: matchData() vracia prázdne pole, ak routa neobsahuje dynamické premenné. Pred použitím overte existenciu kľúča, napr. isset($request->matchData()['id']), aby ste predišli chybám.
5. Middleware (Before a After Hooks)
Middleware v Routeri DotApp Frameworku umožňuje vykonávať dodatočnú logiku pred alebo po hlavnom handleri routy. Tieto „hooks“ sú definované pomocou metód before() a after() a sú ideálne na úlohy ako autentifikácia, logovanie alebo úprava odpovedí.
5.1 Čo sú hooks?
Hooks sú funkcie, ktoré sa spúšťajú automaticky v určitých fázach spracovania routy:
before: Spustí sa pred hlavnou logikou routy (napr. callbackom alebo controllerom).after: Spustí sa po hlavnej logike, s prístupom k výsledku routy.
Hooks prijímajú objekt $request ako parameter a môžu byť definované globálne, pre konkrétnu routu alebo pre metódu s routou.
5.2 Definovanie before()
Metóda before() sa používa na pridanie logiky, ktorá sa vykoná pred hlavným handlerom. Môže byť použitá tromi spôsobmi:
- Globálne: Pre všetky routy.
- Pre konkrétnu routu: Len pre zadanú cestu.
- Pre metódu a routu: Špecificky pre HTTP metódu a cestu.
Globálne before:
Router::before(function ($request) {
return "Before every route!";
});
Router::get('/test', function ($request) {
return "Test page";
});
Hook sa spustí pre všetky routy, napr. pri /test sa najskôr vykoná "Before every route!".
Before pre konkrétnu routu:
Router::get('/secure', function ($request) {
return "Secure page";
})->before(function ($request) {
return "Verifying access...";
});
Hook sa spustí len pre /secure.
Before s metódou a routou:
Router::before('get', '/login', function ($request) {
return "Checking login for GET";
});
Router::get('/login', function ($request) {
return "Login page";
});
5.3 Definovanie after()
Metóda after() sa spúšťa po hlavnom handleri a má rovnaké možnosti definovania ako before(). Je užitočná na úpravu výsledkov alebo logovanie.
Globálne after:
Router::after(function ($request) {
return "After every route!";
});
Router::get('/test', function ($request) {
return "Test page";
});
Hook sa spustí po každej route, napr. pri /test sa najskôr vykoná "Test page" a potom "After every route!".
After pre konkrétnu routu:
Router::get('/profile', function ($request) {
return "Profile page";
})->after(function ($request) {
return "Profile has been displayed";
});
After s metódou a routou:
Router::after('post', '/submit', function ($request) {
return "Form has been processed";
});
Router::post('/submit', function ($request) {
return "Submission successful";
});
5.4 Použitie s viacerými routami
Hooks môžete priradiť viacerým routám naraz pomocou poľa ciest v metóde match() alebo samostatným volaním before()/after().
Príklad s match:
Router::match(['get'], ['/home', '/index'], function ($request) {
return "Homepage";
})->before(function ($request) {
return "Before the homepage";
})->after(function ($request) {
return "After the homepage";
});
Hooky sa aplikujú na obe cesty: /home aj /index.
Príklad s poľom ciest:
Router::before('get', ['/page1', '/page2'], function ($request) {
return "Before the pages";
});
Router::get('/page1', function ($request) {
return "Page 1";
});
Router::get('/page2', function ($request) {
return "Page 2";
});
Poznámka: Výstup z hooks sa pripája k odpovedi routy. Ak chcete meniť odpoveď, pracujte priamo s $request->response->body v hooku (viac v pokročilých funkciách).
6. Správa chýb a výnimiek
Router v DotApp Frameworku umožňuje vývojárom spravovať chyby a výnimky, ktoré vznikajú pri spracovaní požiadaviek. Táto kapitola popisuje, ako riešiť štandardné chyby ako 404 a implementovať vlastnú logiku spracovania chýb pomocou callbackov a hooks.
6.1 Riešenie 404 chýb
Ak Router nenájde zhodu, spustí udalosť dotapp.router.resolve.404. Ak ju žiadny listener nespracuje, Router::errorHandle(404, $view) môže vykresliť error_{$view}. Inak framework odošle prázdnu odpoveď 404 a skončí.
Preferovaný spôsob: event listener v module.listeners.php
use Dotsystems\App\Parts\Events;
use Dotsystems\App\Parts\Response;
Events::on('dotapp.router.resolve.404', function () {
return new Response(404, 'Page not found');
});
Alternatíva: pomenované chybové view
Router::errorHandle(404, 'notfound');
Hľadá sa view s názvom error_notfound. Listener alebo chybové view zaregistrujte z modulu.
6.2 Vlastné spracovanie chýb
Vývojári môžu implementovať vlastnú logiku spracovania chýb priamo v callbackoch alebo middleware pomocou podmienok a HTTP kódov.
Príklad s podmienkou v callbacku:
Router::get('/user/{id:i}', function ($request) {
$id = $request->matchData()['id'];
if ($id > 100) {
http_response_code(403);
return "Access forbidden for IDs greater than 100!";
}
return "User profile: $id";
});
Pri /user/150 sa zobrazí "Access forbidden for IDs greater than 100!" s kódom 403.
Príklad s middleware:
Router::get('/user/{id:i}', function ($request) {
$id = $request->matchData()['id'];
return "User profile: $id";
})->before(function ($request) {
$id = $request->matchData()['id'];
if (!isset($id)) {
http_response_code(400);
return "ID is missing!";
}
});
Pri /user/ sa zobrazí "ID is missing!" s kódom 400.
Poznámka: Použitie http_response_code() v callbackoch alebo hooks umožňuje nastaviť vlastné chybové stavy. Je na vývojárovi, či skript ukončí pomocou exit alebo vráti chybovú správu.
7. Pokročilé funkcie
Router v DotApp Frameworku ponúka pokročilé funkcie, ktoré rozširujú jeho možnosti. Táto kapitola popisuje reťazenie metód, dynamické porovnávanie URL, detailné vysvetlenie tvorby dynamických adries a definovanie API endpointov.
7.1 Reťazenie metód
Router podporuje reťazenie metód, čo umožňuje definovať routy, hooks a ďalšie nastavenia v jednom príkaze. To zlepšuje čitateľnosť a organizáciu kódu.
Príklad reťazenia:
Router::get('/profile/{id}', function ($request) {
$id = $request->matchData()['id'];
return "Profile ID: $id";
})->before(function ($request) {
return "Checking before displaying the profile";
})->after(function ($request) {
return "Profile displayed";
});
Pri /profile/123 sa postupne spustí before, hlavná logika a after.
7.2 Dynamické porovnávanie rout (matchUrl())
Metóda matchUrl() slúži na manuálne porovnanie URL s routovacím vzorom. Vráti pole extrahovaných premenných, ak sa vzor zhoduje, alebo false, ak nie. Je užitočná pre vlastné validácie alebo testovanie rout.
Príklad použitia:
Router::get('/test', function ($request) {
$pattern = '/user/{id:i}';
$url = '/user/123';
$match = Router::matchUrl($pattern, $url);
if ($match !== false) {
return "Match! ID: " . $match['id'];
}
return "No match";
});
Pri /test sa zobrazí "Match! ID: 123".
7.3 Dynamické adresy a vzory
Dynamické adresy v Routeri umožňujú definovať routy s premennými a voliteľnými časťami pomocou špeciálnej syntaxe. Tieto vzory sú rozpoznávané všade rovnako (napr. v get(), post(), match()) a premenné sú dostupné cez $request->matchData(). Nasleduje podrobné vysvetlenie na príklade a zoznam najčastejších vzorov.
Príklad dynamickej adresy:
Router::get('/documentation/intro(?:/{language})?', function ($request) {
$language = $request->matchData()['language'] ?? 'default';
return "Introductory documentation, language: $language";
});
Vysvetlenie:
/documentation/intro(?:/{language})?: Definuje routu, kde{language}je voliteľná časť (označená?:a?)./documentation/intro: Platná (jazyk je "default")./documentation/intro/eng: Platná (jazyk je "eng")./documentation/intro/: Neplatná (Routeročakáva hodnotu za lomítkom, ak je prítomné).
Premenná language sa extrahuje do $request->matchData(), ak je zadaná, inak je null.
Najčastejšie používané vzory:
Tu je zoznam 10 bežných vzorov dynamických adries, ktoré sa používajú vo webových aplikáciách, s príkladmi a vysvetlením:
/{resource}/{id:i}- Základná CRUD routaRouter::get('/users/{id:i}', function ($request) { return "User ID: " . $request->matchData()['id']; });Platné:
/users/123, Neplatné:/users/abc/{category}/{slug:s}- Kategória a slug článkuRouter::get('/blog/{category}/{slug:s}', function ($request) { return "Category: " . $request->matchData()['category'] . ", Slug: " . $request->matchData()['slug']; });Platné:
/blog/tech/how-to-code/api/v{version}/{endpoint}- Verzované APIRouter::get('/api/v{version}/{endpoint}', function ($request) { return "API v" . $request->matchData()['version'] . ": " . $request->matchData()['endpoint']; });Platné:
/api/v1/users/{page}(?:/{subpage})?- Voliteľná podstránkaRouter::get('/docs/{page}(?:/{subpage})?', function ($request) { $subpage = $request->matchData()['subpage'] ?? 'main'; return "Page: " . $request->matchData()['page'] . ", Subpage: $subpage"; });Platné:
/docs/intro,/docs/intro/setup/{type}/{id:i}/{action}- Akcia na zdrojiRouter::get('/posts/{id:i}/{action}', function ($request) { return "ID: " . $request->matchData()['id'] . ", Action: " . $request->matchData()['action']; });Platné:
/posts/5/edit/{resource}/{filter:s?}- Voliteľný filterRouter::get('/products/{filter:s?}', function ($request) { $filter = $request->matchData()['filter'] ?? 'all'; return "Products, filter: $filter"; });Platné:
/products,/products/new/{path*}- Wildcard pre celú cestuRouter::get('/files/{path*}', function ($request) { return "File path: " . $request->matchData()['path']; });Platné:
/files/images/photo.jpg/{lang:l}/{section}- Jazyk a sekciaRouter::get('/{lang:l}/{section}', function ($request) { return "Language: " . $request->matchData()['lang'] . ", Section: " . $request->matchData()['section']; });Platné:
/en/news, Neplatné:/123/news/search(?:/{query})?- Voliteľný vyhľadávací reťazecRouter::get('/search(?:/{query})?', function ($request) { $query = $request->matchData()['query'] ?? 'empty'; return "Search: $query"; });Platné:
/search,/search/php/{resource}/{id:i}(?:/{extra})?- Zdroj s voliteľným parametromRouter::get('/users/{id:i}(?:/{extra})?', function ($request) { $extra = $request->matchData()['extra'] ?? 'none'; return "ID: " . $request->matchData()['id'] . ", Extra: $extra"; });Platné:
/users/10,/users/10/details
Poznámka: Tieto vzory sú flexibilné a kombinovateľné. Používajte {?:} pre voliteľné časti a typy (:i, :s, :l) pre presné obmedzenia.
7.4 Definovanie API endpointov pomocou apiPoint
Metóda apiPoint v Routeri poskytuje pohodlný spôsob, ako definovať API endpointy s podporou verzovania, modulov a dynamických parametrov. Umožňuje flexibilitu pri definovaní vlastných ciest a metód a v kombinácii so vstavanou abstraktnou triedou Controller a jej metódami apiDispatch (hlavná logika) a api (kratší alias) ponúka automatické rozbočovanie požiadaviek na konkrétne metódy controlleru s podporou dependency injection (DI).
Definícia
Router::apiPoint($version, $module, $controller, $custom = null);
Parametre:
$version: Verzia API (napr."1"pre v1).$module: Názov modulu (napr."shop").$controller: Callback alebo reťazec vo formáte"Module:Controller@method!"(napr."HelloWorld:Posts@apiDispatch!","HelloWorld:Posts@api!", alebo vlastná metóda).$custom(voliteľné): Špecifická cesta (reťazec) alebo pole ciest. Podporuje regulárne výrazy (napr.(?:/{id})?).
Ak $custom nie je zadaný, použije sa predvolená dynamická cesta /api/v{version}/{module}/{resource}(?:/{id})?. Ak je zadaný, použijú sa iba cesty z $custom. Prvá routa víťazí! Statické cesty musia byť uvedené pred dynamickými, aby ich neprekryla dynamická logika.
Vstavaný Controller a metódy apiDispatch/api:
Framework poskytuje abstraktnú triedu Dotsystems\App\Parts\Controller s metódou apiDispatch, ktorá automaticky rozbočuje požiadavky na konkrétne metódy v tvare (napr. postUsers, getPosts) na základe HTTP metódy a hodnoty dynamického parametra resource. Nasmerujte apiPoint na Controller@apiDispatch (alebo Controller@api ako kratší alias). Automatické rozbočovanie funguje, keď cesta obsahuje {resource}. Pre každú metódu zdroja nemusíte registrovať samostatnú routu.
apiDispatch mapuje HTTP metódu + resource na metódu controlleru s názvom {method}{Resource}, napríklad GET …/posts → getPosts($request). Tieto metódy implementujte ako public static. Ak sa žiadna metóda nezhoduje, spustí sa error404($request), ak existuje; inak framework vráti HTTP 404. Dispatcher zaregistrujte s koncovou !:
Router::apiPoint("1", "shop", "HelloWorld:Posts@apiDispatch!");
Prispôsobenie chýb:
Ak cieľová metóda (napr. postUsers) neexistuje, apiDispatch najprv skontroluje, či controller definuje metódu error404. Ak áno, zavolá ju a umožní vám definovať vlastnú logiku pre 404 chyby (napr. JSON odpoveď, logovanie). Ak error404 nie je prítomná, vráti predvolenú chybovú hlášku s HTTP kódom 404.
Použitie s automatickým rozbočovaním:
Automatické rozbočovanie cez apiDispatch (alebo api) funguje iba vtedy, ak cesta obsahuje dynamický parameter {resource} na správnom mieste (napr. /api/v1/shop/{resource}). Ak $custom nezachová tento formát, automatika nebude fungovať a je potrebné použiť vlastnú metódu.
Príklad bez $custom (automatické rozbočovanie):
Router::apiPoint("1", "shop", "HelloWorld:Posts@apiDispatch!");
Výsledné cesty:
POST /api/v1/shop/users- SpustípostUsers, ak existuje.GET /api/v1/shop/posts- SpustígetPosts.GET /api/v1/shop/status- Spustíerror404, ak existuje, inak 404 s predvolenou hláškou./api/v1/shop/posts/- Nezachytí sa.
Príklad s $custom a automatickým rozbočovaním:
Router::apiPoint("1", "shop", "HelloWorld:Posts@apiDispatch!", ["{resource}(?:/{id})?/details"]);
Výsledné cesty:
POST /api/v1/shop/users/details- SpustípostUsers.GET /api/v1/shop/posts/details- SpustígetPosts.GET /api/v1/shop/posts/abc123/details- SpustígetPosts.PUT /api/v1/shop/status/details- Spustíerror404, ak existuje, inak 404 s predvolenou hláškou./api/v1/shop/users/- Nezachytí sa.
Príklad s vlastnými routami a vlastnou metódou:
Router::apiPoint("1", "shop", "HelloWorld:Posts@customMethod!", ["users/details", "posts/summary"]);
Výsledné cesty: Automatické rozbočovanie tu nefunguje, pretože chýba {resource}. Logika závisí od implementácie customMethod.
GET /api/v1/shop/users/details- SpustícustomMethod.POST /api/v1/shop/posts/summary- SpustícustomMethod.
Príklad controlleru s DI a vlastnou chybou:
namespace Dotsystems\App\Modules\Dotcmsfe\Controllers;
class Posts extends \Dotsystems\App\Parts\Controller {
public static function postUsers($request, \SomeService $service) {
return "Creating users: " . $service->process($request->getPath());
}
public static function getPosts($request) {
$id = $request->matchData()['id'] ?? null;
return "List of posts" . ($id ? " with ID: $id" : "");
}
public static function error404($request) {
http_response_code(404);
return json_encode([
'error' => 'Not Found',
'message' => "Resource '{$request->matchData()['resource']}' not found or method '{$request->getMethod()}' not supported",
'path' => $request->getPath()
]);
}
public static function customMethod($request) {
return "Custom method for path: " . $request->getPath();
}
}
Poznámka: Vstavaný Controller zjednodušuje prácu s API cez apiDispatch (alebo api), ak cesta obsahuje {resource}. Pre vlastné routy bez {resource} môžete použiť vlastné metódy, ale automatické rozbočovanie nebude fungovať. Poradie ciest v $custom je kritické – statické cesty musia byť pred dynamickými.
8. Praktické príklady
Táto kapitola prináša praktické príklady použitia Routera v DotApp Frameworku. Ukazuje, ako kombinovať základné a pokročilé funkcie na riešenie bežných scenárov vo webových aplikáciách.
8.1 Jednoduchá GET routa
Najzákladnejší príklad definovania statickej routy s jednoduchou odpoveďou.
Príklad:
Router::get('/welcome', function ($request) {
return "Welcome to the application!";
});
Pri požiadavke na /welcome sa zobrazí: "Welcome to the application!".
Použitie: Ideálne pre statické stránky, ako sú úvodné stránky alebo „O nás“.
8.2 Dynamická routa s premennými
Príklad dynamickej routy s extrakciou premenných na zobrazenie údajov o používateľovi.
Príklad:
Router::get('/user/{id:i}/{name}', function ($request) {
$id = $request->matchData()['id'];
$name = $request->matchData()['name'];
return "User ID: $id, Name: $name";
});
Pri /user/123/Jano sa zobrazí: "User ID: 123, Name: Jano".
Použitie: Vhodné pre profily, detaily produktov alebo iné zdroje s identifikátormi.
8.3 Použitie middleware
Príklad kombinácie routy s before a after hooks na overenie a logovanie.
Príklad:
Router::get('/dashboard', function ($request) {
return "Welcome to the dashboard!";
})->before(function ($request) {
$user = "guest"; // Simulated verification
if ($user === "guest") {
http_response_code(403);
return "Access denied!";
}
})->after(function ($request) {
return "Dashboard displayed at " . date('H:i:s');
});
Pri /dashboard sa zobrazí "Access denied!" s kódom 403 (keďže simulované overenie zlyhá). Ak by overenie uspelo, zobrazilo by sa "Welcome to the dashboard!" a následne čas zobrazenia.
Použitie: Autentifikácia, logovanie prístupu alebo úprava odpovedí.
8.4 Kombinácia s controllermi
Príklad integrácie routy s controllerom na oddelenie logiky od routingu.
Príklad:
// app/modules/HelloWorld/Controllers/Article.php
namespace Dotsystems\App\Modules\HelloWorld\Controllers;
class Article extends \Dotsystems\App\Parts\Controller {
public static function detail($request) {
$slug = $request->matchData()['slug'];
return "Article detail: $slug";
}
}
// Route definition
Router::get('/article/{slug:s}', 'HelloWorld:Article@detail!');
Pri /article/how-to-code sa zobrazí: "Article detail: how-to-code".
Použitie: Väčšie aplikácie, kde je potrebná organizácia kódu do controllerov.
9. Tipy a triky
Táto kapitola ponúka praktické tipy a triky na efektívne využitie Routera v DotApp Frameworku. Pomôžu vám optimalizovať kód, ladiť problémy a dodržiavať osvedčené postupy.
9.1 Optimalizácia routingu
Router v DotApp Frameworku funguje na princípe „prvý match víťazí“ – prvá zhodujúca sa routa v poradí definovania sa použije a ostatné sa ignorujú, bez ohľadu na to, či je routa statická alebo dynamická. Poradie definovania je preto kľúčové pre optimalizáciu.
- Definujte najdôležitejšie routy najskôr: Keďže prvý match víťazí, umiestnite kritické alebo častejšie používané routy na začiatok.
- Používajte špecifické vzory: Napr.
{id:i}namiesto{id}, aby ste zabránili nechceným zhôdám na nesprávnych routách. - Zoskupte podobné routy: Použite
match()s poľom ciest na zníženie duplicity kódu, ale dávajte pozor na poradie.
Príklad optimalizácie:
Router::get('/user/{id:i}', function ($request) { // First dynamic route
return "Dynamic user ID: " . $request->matchData()['id'];
});
Router::get('/user/123', function ($request) { // Second static route
return "Static user 123";
});
Pri /user/123 vždy vyhrá prvá routa ("Dynamic user ID: 123"), pretože bola definovaná ako prvá, aj keď druhá je statická a presnejšia. Ak chcete prioritu pre statickú routu, definujte ju skôr.
Príklad so zmeneným poradím:
Router::get('/user/123', function ($request) { // First static route
return "Static user 123";
});
Router::get('/user/{id:i}', function ($request) { // Second dynamic route
return "Dynamic user ID: " . $request->matchData()['id'];
});
Teraz sa pri /user/123 zobrazí "Static user 123", pretože je definovaná ako prvá.
9.2 Ladenie rout
Pri ladení problémov s routami použite dostupné nástroje Routera a PHP na identifikáciu, ktorá routa sa skutočne spúšťa, najmä pri pravidle „prvý match“.
- Skontrolujte cestu: Použite
$request->getPath()na overenie, akú URLRouterspracováva. - Výpis premenných: Vypíšte
$request->matchData(), aby ste videli, aké hodnoty boli extrahované. - Testujte poradie: Pridajte dočasné výpisy (napr.
echo) do callbackov, aby ste zistili, ktorá routa sa spustila.
Príklad ladenia:
Router::get('/page/{id}', function ($request) {
echo "Dynamic route triggered for ID: " . $request->matchData()['id'];
return "Dynamic page " . $request->matchData()['id'];
});
Router::get('/page/1', function ($request) {
echo "Static route triggered for /page/1";
return "Static page 1";
});
Pri /page/1 sa zobrazí "Dynamic route triggered for ID: 1" a "Dynamic page 1", pretože dynamická routa je definovaná ako prvá. Zmena poradia by uprednostnila statickú routu.
9.3 Best practices pre štruktúru rout
Dodržiavanie osvedčených postupov pomáha udržať prehľadnosť a predvídateľnosť routingu.
- Logické poradie: Definujte routy od najšpecifickejších po najvšeobecnejšie, aby ste využili pravidlo „prvý match víťazí“.
- Komentáre: Pridávajte komentáre nad routy, aby bolo jasné, prečo sú v danom poradí.
- Oddelenie logiky: Používajte controllery pre komplexné routy namiesto inline callbackov.
Príklad best practices:
// Most specific static route
Router::get('/api/users/guest', function ($request) {
return "Guest user";
});
// Specific dynamic route
Router::get('/api/users/{id:i}', function ($request) {
return "User ID: " . $request->matchData()['id'];
});
// General route last
Router::get('/api/{resource}', function ($request) {
return "Resource: " . $request->matchData()['resource'];
});
Pri /api/users/guest sa spustí prvá routa, pri /api/users/5 druhá a pri /api/products tretia, vďaka logickému poradiu.
10. Záver
Táto kapitola uzatvára dokumentáciu Routera v DotApp Frameworku. Zhŕňa jeho výhody a ponúka pohľad na jeho budúci vývoj a komunitu.
10.1 Prečo používať Router v DotApp?
Router v DotApp Frameworku je jednoduchý, no výkonný nástroj na správu routingu vo webových aplikáciách. Jeho hlavné výhody zahŕňajú:
- Flexibilita: Podpora statických aj dynamických rout s premennými a voliteľnými časťami.
- Jednoduchosť: Intuitívne rozhranie na definovanie rout cez HTTP metódy ako
get()apost(). - Middleware: Možnosť pridania
beforeaafterhooks pre rozšírenú logiku. - Prvý match víťazí: Predvídateľné správanie založené na poradí definovania rout, čo dáva vývojárom plnú kontrolu.
- Integrácia: Bezproblémová spolupráca s controllermi a objektom
Requestna spracovanie požiadaviek.
Či už tvoríte malú aplikáciu alebo komplexný systém, Router vám poskytne nástroje na rýchle a efektívne mapovanie požiadaviek na logiku.