SeoRouter

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Foowie
Člen | 269
+
0
-

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.

Kompletní ukázka ke stáhnutí

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
+
0
-

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();
	}
}
?>