3. úroveň odkazu v RouterFactory
- ForestCZE
- Člen | 209
Ahoj všichni, narazil jsem na jeden problém a vůbec nevím, jak jej vyřešit. Existují v Nette odkazy „3. úrovně“? (Nevím, jak lépe to nazvat)
Příklad:
Budu mít Linux, v něm distribuci a v distribuci dané téma.
Odkaz by vypadal nějak
takto: http://mojedomena.cz/linux/ubuntu/tutorialy
Což tedy znamená, že linux bude presenter, ubuntu bude action a tutorialy už nevím.
Předpokládám, že to budu muset nastavit v routě.
public static function createRouter()
{
$frontModule = new RouteList('Front');
$frontModule[] = new Route('<linux>/<ubuntu>/<action>', ''); // Střílím
$frontModule[] = new Route('<presenter>/<action>', 'Home:default');
$router = new RouteList;
$router[] = $frontModule;
return $router;
}
Nebo už to třetí musí být bráno jako parametr?
$frontModule[] = new Route('<linux>/<ubuntu>[/<param1>]', ''); //Kam by to pak odkazovalo?
Budu moc vděčný za ukázku a vysvětlení.
- CZechBoY
- Člen | 3608
Tak samozrejme zalezi na tobe, z toho co si napsal neni uplne jasny co se snazis udelat…
3 (a vic) urovne bez parametry jdou udelat pres modul-presenter-action, případně moduly-submodul-presenter-default akce.
Spis to ale vypada ze hledas 1 presenter s 1 parametrem a to bude cesta k clanku/kategorii clanku?
- ForestCZE
- Člen | 209
CZechBoY napsal(a):
Tak popis co programujes :-)
Popsal jsem. Odkaz „3. úrovně“. Dal jsem příklad odkazu, jak potřebuji, aby vypadal.
http://mojedomena.cz/linux/ubuntu/tutorialy
Kde linux je kategorie, ubuntu je podkategorie a tutorialy je okruh příspěvků, které vytáhnu z databáze. Co víc k tomu říct?
- ForestCZE
- Člen | 209
Tak jsem to zkusil takto:
public static function createRouter()
{
$frontModule = new RouteList('Front');
$frontModule[] = new Route('<presenter>/<action>', 'Home:default');
$frontModule[] = new Route("<tutorialy>", [
"presenter" => "Linux",
"action" => "ubuntu",
"tutorialy" => [
Route::FILTER_OUT => null,
Route::PATTERN => ".*?"
]
]);
$router = new RouteList;
$router[] = $frontModule;
return $router;
}
A vyleze mi z toho:
http://mojedomena.cz/linux/ubuntu?tutorialy=linux%2Fubuntu%2Ftutorialy%2F
Co dělám špatně?
Editoval ForestCZE (3. 5. 2018 12:18)
- ForestCZE
- Člen | 209
CZechBoY napsal(a):
Přehoď pořadí rout.
To jsem původně měl, ale hodí mi to dva redirecty, pokud zadám do
prohlížeče: http://mojedomena.cz/
, tak mě to přesměruje
na: http://mojedomena.cz/linux/ubuntu/
EDIT: A navíc když kliknu na jakýkoliv odkaz, tak URL je v pohodě, ale načte se Front:Linux:ubuntu
Vážně si nevím rady, omlouvám se a děkuji za trpělivost, především @CZechBoY
Editoval ForestCZE (3. 5. 2018 14:08)
- duke
- Člen | 650
@ForestCZE To lze vyřešit tak, že routě s maskou <tutorialy> přidáš FILTER_IN filtrovací funkci, kde odfiltruješ všechny hodnoty, které nejsou tutoriály (vrátíš null). Tím, že to neděláš, tak ta routa přijímá cokoli (což nechceš). To následné přesměrování je pak důsledek toho, že Nette kvůli kanonickým (neduplicitním) url v zájmu SEO přesměrovává na url, generované touto (prioritní) routou.
- duke
- Člen | 650
ForestCZE napsal(a):
@duke Chápu, jak to myslíš, ale nevím, jak to napsat. Mohl bys mi s tím prosím pomoct? Už tak jsem rád, že jsem dal dohromady to, co mám teď. Moc díky.
$frontModule[] = new Route("<tutorialy>", [
"presenter" => "Linux",
"action" => "ubuntu",
"tutorialy" => [
// $tutorials je služba, která umí ověřit, zda existuje tutorial s daným url
Route::FILTER_IN => function ($tutorialy) use ($tutorials) {
return $tutorials->exists($tutorialy) ? $tutorialy : null;
},
Route::FILTER_OUT => null,
Route::PATTERN => ".*?"
]
]);
- ForestCZE
- Člen | 209
duke napsal(a):
Ještě tedy nechápu to:
"presenter" => "Linux", "action" => "ubuntu",
Tam bys měl mít spíš jen:
"presenter" => "Tutorials", "action" => "default",
@duke No já právě nevím, jestli to mám dobře.
Mám presenter: presenters/LinuxPresenter.php a pak template: presenters/templates/Linux/ubuntu.latte, což znamená, že ta cesta bude: neco.cz/linux/ubuntu a pak potřebuji rozdělení té ubuntu:
/linux/ubuntu/tutorialy
/linux/ubuntu/necodalsiho1
/linux/ubuntu/necodalsiho2
Pak mi právě není jasné, proč je presenterem Tutorials a ne Linux
- duke
- Člen | 650
No máš minimálně dvě možnosti. Buď to vše bude řešit jeden presenter Tutorials, který bude mít parametr obsahující cestu, tj.:
class TutorialsPresenter extends BasePresenter
{
/** @var string @persistent */
public $path;
public function renderDefault($path)
{
// TODO: podle $path nastavit šablonu a její obsah
// v $path bude např. "linux/ubuntu/instalace
}
}
s routováním:
$frontModule[] = new Route("<path>", [
"presenter" => "Tutorials",
"action" => "default",
"path" => [
Route::FILTER_IN => function ($path) use ($tutorials) {
return $tutorials->exists($path) ? $path : null;
},
Route::FILTER_OUT => null,
Route::PATTERN => ".*?"
]
]);
Nebo to řešit individuálními presentery a akcemi:
class LinuxPresenter extends BasePresenter
{
/** @var string @persistent */
public $topic;
public function renderUbuntu($topic)
{
// TODO: podle $topic nastavit šablonu a její obsah
// v $topic bude např. "instalace"
}
public function renderFedora($topic)
{
// TODO: podle $topic nastavit šablonu a její obsah
// v $topic bude např. "instalace"
}
}
s routováním:
$frontModule[] = new Route("<presenter>/<action>/<topic>", [
"topic" => [
Route::FILTER_OUT => null,
Route::PATTERN => ".*?"
],
null => [
Route::FILTER_IN => function (array $params) use ($tutorials) {
return $tutorials->exists("$params[presenter]/$params[action]/$params[topic]")) ? $params : null;
}
],
]);
Netestováno, takže to může obsahovat nějaký chyby, či nedomyšlenosti.
Ale snad jsem tě alespoň nasměroval…
Já bych spíše zvolil tu první variantu. Tzn. to rozdělení do šablon bych
řešil v té render metodě, než pro toto „zneužívat“ akce a
presentery.
- duke
- Člen | 650
$tutorials je služba, kterou si tam přidáš přes dependency injection. Např. nějaký repozitář či fasáda řešící tutorialy.
Co se týče nastavení šablony, tak k tomu slouží metoda formatTemplateFiles, která vrací pole cest k šablonám, ze kterého se vezme první existující. Můžeš ji tedy překrýt např. takto:
public function formatTemplateFiles()
{
$filePaths = parent::formatTemplateFiles();
array_unshift($filePaths, __DIR__ . "/templates/{$this->path}.latte");
return $filePaths;
}
Asi by bylo ale dobré zkontrolovat, zda $this->path neobsahuje něco, co nemá…
Metoda setView se volá zpravidla v action metodách a umožňuje nastavit, která render metoda se bude následně volat. Nicméně to má dopad i na to, co pak vrací výchozí implementace metody formatTemplateFiles, takže ano, i setView metodu lze k tomuto teoreticky použít, byť to v tomto případě nedoporučuji (potenciální problémy s lomítky v hodnotě view, atp.).
Editoval duke (3. 5. 2018 23:39)