SeoRouter
- Foowie
- Člen | 269
Trošku jsem experimentoval se SimpleSeoRouterem, ale potřeboval jsem jich
celkem hodně.
Nakonec jsem se rozhodl udělat potomka od Route a do něj to „Seo“
zakomponovat. Původně jsem do Route.php nechtěl vůbec šahat, ale nakonec,
po uvážení, že by většina věcí měla proběhnout 2×, jsem vložil do
Route uživatelsky definovatelný callback.
Do konstruktoru přibyl čtvrtý parametr, pole, obsahující seznam
parametrů, které mají projet user-friendly-url překladem. Každá položka
může nabývat buď hodnoty null (nebude se cachovat), nebo pole závislostí
na ostatních parametrech. (Například pokud má parametr ID v každém
presenteru jiný význam, vypadá čtvrtý parametr konstrukotru takto:
array( "id" => array("presenter") )
(Pokud je ve čtvrtém
parametru konstruktoru více parametrů, musí být tyto parametry závislé jen
na parametrech co jsou od něj na levé straně … zatím to nevyhazuje
výjimku ale až bude zase chuť tak bude :p)
Dále se, jako u SimpleSeoRouteru, musí SeoRouter podědit a překrýt
abstraktní metody getId($parameterName, array $params)
a
getUrl($parameterName, array $params)
. $parameterName
je jméno parametru, který se má přeložit a $params
obsahuje
seznam parametrů a jejich hodnot, včetně modulu a presenteru, je-li
v prvním parametru konstruktoru definován.
SeoRouter využívá cache a defaultně je nastavená expirace jeden den, od
vložení prvního záznamu…
- Například v galerii co těďka dělám, je presenter Images
- actions: tag, author, section, gallery
- parameters:
- id = tag, author, section, gallery
- imageId = aktuálně zobrazovaný obrázek
Zde je význam parametru id
závislý na action. Parametr
imageId
je v téhle routě nezávislý.
Příklady výsledných url:
http://www.domena.cz/tag-skala/clovek-padajici-ze-skaly
http://www.domena.cz/section-lide/dav-900-lidi
http://www.domena.cz/gallery-nocni-obloha/zarici-hevzdy
bootstrap.php
<?php
$router[] = new ImagesSeoRouter(
"<action>-<id>/<imageId>",
array(
"presenter" =>"Images",
"imageId" => null,
), 0,
array(
"id" => array("action"),
"imageId" => array(),
)
);
?>
ImagesSeoRouter (ty sql dotazy jsou původně v modelu)
<?php
class ImagesSeoRouter extends SeoRouter
{
protected function getId($parameterName, array $params) {
$id = null;
switch($parameterName) { // Rozdělení podle jména parametru
case("id"): {
switch($params[self::ACTION_KEY]) { // Rozdělení podle action
case("section"): {
$id = dibi::query("SELECT [id] FROM %n WHERE [url]=%s", Sections::TABLE, $params[$parameterName]);
} break;
case("tag"): {
$id = dibi::query("SELECT [id] FROM %n WHERE [url]=%s", Tags::TABLE, $params[$parameterName]);
} break;
case("author"): {
$id = dibi::query("SELECT [id] FROM %n WHERE [url]=%s", Users::TABLE, $params[$parameterName]);
} break;
case("gallery"): {
$id = dibi::query("SELECT [id] FROM %n WHERE [url]=%s", Galleries::TABLE, $params[$parameterName]);
} break;
}
} break;
case("imageId"): {
$id = dibi::query("SELECT [id] FROM %n WHERE [url]=%s", Images::TABLE, $params[$parameterName]);
} break;
}
return ($id != null) ? $id->fetchSingle() : $params[$parameterName];
}
protected function getUrl($parameterName, array $params) {
$url = null;
switch($parameterName) {
case("id"): {
switch($params[self::ACTION_KEY]) {
case("section"): {
$url = dibi::query("SELECT [url] FROM %n WHERE [id]=%i", Sections::TABLE, $params[$parameterName]);
} break;
case("tag"): {
$url = dibi::query("SELECT [url] FROM %n WHERE [id]=%i", Tags::TABLE, $params[$parameterName]);
} break;
case("author"): {
$url = dibi::query("SELECT [url] FROM %n WHERE [id]=%i", Users::TABLE, $params[$parameterName]);
} break;
case("gallery"): {
$url = dibi::query("SELECT [url] FROM %n WHERE [id]=%i", Galleries::TABLE, $params[$parameterName]);
} break;
}
} break;
case("imageId"): {
$url = dibi::query("SELECT [url] FROM %n WHERE [id]=%i", Images::TABLE, $params[$parameterName]);
} break;
}
return ($url != null) ? $url->fetchSingle() : $params[$parameterName];
}
}
?>
Věřím, že je tam bugů do aleluja, ale pro tenhle relativně jednoduchý příklad to funguje =)
… Zatím, pokud se překlad nenajde, tak se nepřekládá. Ale přemýšlím, jestli by spíše neměl router vyhodit null…
- Foowie
- Člen | 269
Trošku jsem to upravil, aby se nemuselo dědit. (Avšak stále funguje postup výše uvedeným způsobem)
V konstruktoru přibyl ještě jeden parametr (defaultně null). Jeho struktura je následující:
<?php
array(
array("nazev-parametru", $model, "parametr"=>"hodnota", "dalsi-parametr"=>"hodnota"),
array("id", new Model(), "presenter"=>"Default"),
...
)
?>
Kde nazev-parametru
je jméno parametru které se bude
překládat a $model
je objekt, který musí implementovat
rozhraní IUrlTranslatable
.
Upravený příklad z minulého postu:
bootstrap.php
<?php
$router[] = new SeoRouter(
"<action>-<id>/<imageId>",
array(
"presenter" =>"Images",
"imageId" => null,
), 0,
array(
"id" => array("action"),
"imageId" => array(),
),
array(
array("imageId", new Images()),
array("id", new Sections(), "action"=>"section"),
array("id", new Tags(), "action"=>"tag"),
array("id", new Galleries(), "action"=>"gallery"),
array("id", new Users(), "action"=>"author"),
)
);
?>
Např. model Sections:
<?php
class Sections extends Object implements IUrlTranslatable
{
const TABLE = "sections";
public function getUrlFromId($id, $parameterName, array $params) {
$result = dibi::query("SELECT [url] FROM %n WHERE [id]=%i", self::TABLE, $id);
return ($result == null) ? null : $result->fetchSingle();
}
public function getIdFromUrl($url, $parameterName, array $params) {
$result = dibi::query("SELECT [id] FROM %n WHERE [url]=%s", self::TABLE, $url);
return ($result == null) ? null : $result->fetchSingle();
}
}
?>