$presenter->isLinkCurrent() a FILTER_OUT
- petr.pavel
- Člen | 535
Zdarec,
zdá se, že nastavení $current
v
Presenter::createRequest()
, část zpracovávající $args,
nespolupracuje s routerem a jeho filtry.
Řádka 945 ve \Nette-2.2.2\Nette\Application\UI\Presenter.php. (Na API prokliknout nemůžu, protože celý createRequest() chybí.)
Akci prezenteru předávám slug, který je vytvořen pomocí FILTER_OUT ze
jména přes Strings::webalize()
.
Link se vyrobí správně, ale nenastaví se $current
, takže
isLinkCurrent()
a ifCurrent
nefungují.
Nebo mi něco uniklo?
Ochcat se to dá řím, že místo prostého
$presenter->linkCurrent
vyjmenuji jeho cíl i parametry, a
parametr jméno nejdřív proženu webalize
. To samé pak musím
zopakovat u jiného parametru, který mi za určitých okolností FILTER_OUT
NULLuje.
Kromě toho, že je výsledek dlouhý jak prase, duplikuju tím funkčnosti filtrů routeru, což je nesmysl.
Jak to děláte vy?
Už tady padly dva dotazy na stejné téma a bez odezvy. Doufám, že budu
mít víc štěstí.
https://forum.nette.org/…icke-stranky
https://forum.nette.org/…stni-chovani
- petr.pavel
- Člen | 535
Tak co? Nikdo nepoužíváte isLinkCurrent() a filtry v routeru? To bych se divil… :-)
- Tomáš Votruba
- Moderator | 1114
Ahoj, mne by pomohl zadouci kod a nutny kod, abych to mohl snadno nasimulovat. Slovni kod me odrazuje.
- petr.pavel
- Člen | 535
<?php
public function createRouter()
{
Route::addStyle('slug');
Route::setStyleProperty('slug', Route::FILTER_OUT, function($text) {
return Strings::webalize($text);
});
$router = new RouteList();
$router[] = new Route('<presenter>/<action>/<slug>', 'Homepage:default');
}
class HomepagePresenter extends BasePresenter
{
public function renderDefault($slug) {}
}
?>
{var $nazev = "Slovní kód odrazuje"}
<a n:href="Homepage:default $nazev" n:class="$presenter->linkCurrent ? funguje">odkaz jinam</a>
Toto {ifCurrent Homepage:default $nazev}je{else}není{/ifCurrent} aktuální stránka.
Vzniklý odkaz (/homepage/default/slovni-kod-odrazuje) nemá třídu
funguje
, přestože to je adresa aktuální stránky. Věta pod
ním vyjde jako „Toto není aktuální stránka.“.
- petr.pavel
- Člen | 535
Mimochodem, to samé, pokud je routa definovaná bez masky:
<?php
$router[] = new Route('<presenter>/<action>/<slug>', array(
'presenter' => 'Homepage',
'action' => 'default',
'slug' => array(
Route::VALUE => null,
Route::FILTER_OUT => function($text) {
return Strings::webalize($text);
},
)
));
?>
- David Matějka
- Moderator | 6445
budes si muset vymyslet alternativni zpusob kontroly, zda jsou linky stejne. Pri kontrole pomoci isLinkCurrent se to do routeru vubec nedostane
Editoval matej21 (25. 8. 2014 19:00)
- petr.pavel
- Člen | 535
matej21 napsal(a):
budes si muset vymyslet alternativni zpusob kontroly, zda jsou linky stejne. Pri kontrole pomoci isLinkCurrent se to do routeru vubec nedostane
createRequest() jsem studoval – relevantní je spíš řádka 948. Jen jsem doufal, že mi něco uniklo.
Za mě je tohle chyba a divím se, že to dosud nikomu nevadilo.
- Tomáš Votruba
- Moderator | 1114
@petr.pavel Jestli víš, jak ji odstranit, pošli PR.
Co je vlastně cílem? Zvíraznit aktivní stránku? U ní případně
můžeš porovat ID/slug, pracovat tedy s
$activePage
/$activeCategory
.
Jinak addStyle je deprecated, tak pozor na použití.
- petr.pavel
- Člen | 535
Ano, potřebuji zvýraznit aktuální stránku.
Nepochopil jsem, co přesně navrhuješ. Mohl bys nastřelit v pseudo-kódu,
jak by vypadala tahle řádka?
<a n:href=„Homepage:default $nazev“ n:class=„$presenter->linkCurrent
? funguje“>odkaz jinam</a>
deprecated addStyle: No to je paráda. Netušíš, kde bych se dočetl, jak to dělat ponovu? Dokumentace mlčí, ve fóru to nikdo zatím neprobíral. Chtělo by to zavést pravidlo, že se do Nette nesmí nic přidat, pokud autor současně nedoplní dokumentaci.
- David Matějka
- Moderator | 6445
deprecated addStyle: zatim je to deprecated jen v dev (a bude asi v pristi stable). Ja jsem to nikdy nepouzil – vzdy nastavuji filtry konkretni route
jinak imho to vyresit nepujde. Filtry by teoreticky mely byt obousmerne – tedy FILTER_OUT to predela do url podoby a FILTER_IN do toho, co chce aplikacni request, potazmo presenter. tak to resim i ja – v presenterech/sablonach vsude posilam entitu a routa si z toho vezme slug/id nebo co potrebuje. Pri matchovani requestu zas dle id/slugu vybere entitu.
- petr.pavel
- Člen | 535
@enumag: Slug vytvářím dynamicky, unikátnost je již u názvu. Mám špatné zkušenosti se samostatnou definicí slugu, uživatelé ji zapomínají aktualizovat. Na SEO kašlou. Mohl bych slug aktualizovat automaticky, ale současné řešení přes styly a routy mi přijde elegantnější. Jaký máš důvod pro tvrzení, že je moje použití nesmyslné?
- David Matějka
- Moderator | 6445
jak potom vybiras dle slugu, kdyz mas v databazi normalni verzi a pro where mas webalized verzi? jak resis unikatnost?
Editoval matej21 (26. 8. 2014 12:53)
- petr.pavel
- Člen | 535
@matej21: Měl jsem za to, že FILTER_OUT a FILTER_IN jsou sice párové, ale na sobě nezávislé. Tj. můj problém by přidání FILTER_IN nevyřešilo. Jestli jsem to špatně pochopil, můžeš mi to vysvětlit?
- David Matějka
- Moderator | 6445
ano, jsou na sobe nezavisle, ale z principu by presenter, sablony atd. nemely o konkretnich pravidlech routovani vedet (a tedy ze si routovani nejak prevadi vstupy/vystupy).
Kdyz bych tedy do constructUrl poslal nejakej request, to mi vratilo url a tu url poslal do match, mel bych dostat zpet stejny request.
Editoval matej21 (26. 8. 2014 13:02)
- petr.pavel
- Člen | 535
jak potom vybiras dle slugu:
Tabulka má čtyři řádky a vždycky potřebuji načíst všechny (z jiného důvodu). Takže vyhledávání dělám přes smyčku v PHP a webalize.
- David Matějka
- Moderator | 6445
@petr.pavel aha, trochu prasarnicka, no :) jako mas tam problem s tim, ze url nejsou persistentni (pri zmene nazvu je to na jine url) apod.
ale kdybys pridal filter_in a vstupni slug vymenil za ne-webalizovany nazev, tak by to melo vyresit tvuj problem s isLinkCurrent
- petr.pavel
- Člen | 535
Kdyz bych tedy do constructUrl poslal nejakej request, to mi vratilo url a tu url poslal do match, mel bych dostat zpet stejny request.
Proč by to tak mělo být?
Presenter ve createRequest() volá router->constructUrl(), ten se mu stará o routování. Bohužel ale až poté, co předtím presenter vyhodnotil, zda je request na aktuální stránku nebo ne. Podle mě je jen potřeba vyhodnocení provést až na základě url a ne nějakým jednotlivým porovnáváním napůl zpracovaných parametrů. Nechápu ale, proč to takhle autor už neudělal, nějaký důvod pro to mít musel.
Jediný nedostatek takového řešení vidím v případě, že různé requesty se stejným url budou všechny vyhodnocené jako „current“. Nevidím ale, proč by to mělo vadit.
- petr.pavel
- Člen | 535
ale kdybys pridal filter_in a vstupni slug vymenil za ne-webalizovany nazev, tak by to melo vyresit tvuj problem s isLinkCurrent
Kdybych tam neměl ještě ten další parametr, který ve FILTER_OUT
zpracovávám, tak bys měl pravdu.
(Parametr sezóna, který za určitých okolností NULLuji.)
- David Matějka
- Moderator | 6445
Proč by to tak mělo být?
vzdyt to tam pisu, presenter by nemel vedet o pravidlech routovani.
V presenteru pracuju treba s entitou, kterou posilam routeru. Me by vubec
nemelo zajimat, co s tim routovani dela.
Bohužel ale až poté, co předtím presenter vyhodnotil, zda je request na aktuální stránku nebo ne. Podle mě je jen potřeba vyhodnocení provést až na základě url a ne nějakým jednotlivým porovnáváním napůl zpracovaných parametrů
ty parametry jsou zcela zpracovane v ramci aplikacniho requestu. Kdyby ti router ve FILTER_IN vyhazoval stejny request, se kterym pracujes v presenteru, tak by nikde problem nebyl
- petr.pavel
- Člen | 535
Proč je „správné“ mít FILTER_IN i FILTER_OUT:
Asi jsme se nepochopili. Nepotřebuji, aby presenter něco věděl
o routování. Nevidím ale důvod, proč by mělo platit, co říkáš
o request1 → url → match → request2 == request1.
Kdyby ti router ve FILTER_IN vyhazoval stejny request, se kterym pracujes v presenteru, tak by nikde problem nebyl
Jednak si nejsem jistý, jestli máš pravdu, ale i kdyby: považuju to za workaround (vochcávku), ne za řešení.
Editoval petr.pavel (26. 8. 2014 13:36)
- David Matějka
- Moderator | 6445
Nevidím ale důvod, proč by mělo platit, co říkáš o request1 → url → match → request2 == request1.
mohlo by to zpusobit problemy s kanonizaci url a zpusobuje to tvuj problem. V tom druhem requestu by byly videt pravidla routeru, tedy webalizovana url apod. Tyhle upravy parametru jsou proste veci routeru a presenter by o nich nemel nic vedet.
btw, jak si rikal,
Takže vyhledávání dělám přes smyčku v PHP a webalize.
to znamena, ze presenter vi o routovani. Vi, ze ty sice do constructUrl posles „normalni“ nazev, ale router to webalizuje
porovnani url by asi nebylo resenim, ta soucasna kontrola, zda je link aktualni, probiha trochu volneji – kdyz neposles parametry, kontroluje se pouze presenter a akce, kdyz posles parametry, kontroluje se pouze shoda tech danych parametru
- petr.pavel
- Člen | 535
Máš recht, že to vyhledávání v PHP ve smyčce v presenteru není košér. Problém s porovnávání url chápu, máš pravdu, takhle by to nešlo.
Pojďme probrat ten druhý parametr.
<?php
Route::addStyle('season');
Route::setStyleProperty('season', Route::PATTERN, '(\d{4}|)'); // match a year or NULL
Route::setStyleProperty('season', Route::FILTER_OUT, function($season) use ($seasonModel) {
return $seasonModel->getCurrentSeason() == $season ? null : $season;
});
$router[] = new Route('[<season>/]events/<slug>', 'Tournament:detail');
?>
Tahle konstrukce mi zaručí, že se /2014/events/slug přesměruje na /events/slug a že parametr $season má hodnotu jen v případě, že se jedná o archiv. V tomhle použití filtru je taky nějaký problém?
- David Matějka
- Moderator | 6445
tohle by asi bylo lepsi resit defaultni hodnotou „season“, ktera by byla
rovna $seasonModel->getCurrentSeason()
- petr.pavel
- Člen | 535
Jak zajistíš to přesměrovávání, aniž bys duplikoval routy? Je jich hodně, různé presentery.
Edit: Asi bych měl přesněji formulovat otázku:
Jak doplnit FILTER_IN, aby se splnilo tvoje pravidlo o zrcadlové funkci
FILTER_IN a FILTER_OUT, a současně se pro aktuální sezónu rok v url
neobjevil.
Editoval petr.pavel (27. 8. 2014 0:50)
- David Matějka
- Moderator | 6445
jaky presmerovani? jako ze po zadani /2014/events/slug
to
presmeruje na verzi bez roku? imho by to mela zvladnout kanonizace
v presenteru…
- petr.pavel
- Člen | 535
Ano. Co to je kanonizace v prezenteru? Znám jen kanonizaci v routeru.
Považuji tohle za otázku routování, takže jak jsme se shodli :-), presenter by se o to starat neměl.
- enumag
- Člen | 2118
petr.pavel napsal(a):
@enumag: Jaký máš důvod pro tvrzení, že je moje použití nesmyslné?
Odpověděl sis sám:
petr.pavel napsal(a):
Takže vyhledávání dělám přes smyčku v PHP a webalize.
Slug je ideální aktualizovat při každé změně názvu automaticky a ukládat do samostatného sloupce. Ještě ideálnější je uchovávat i staré slugy pro one-way routu aby se staré url přesměrovaly na nové.
petr.pavel napsal(a):
Ano. Co to je kanonizace v prezenteru? Znám jen kanonizaci v routeru.
Kanonizace v presenteru je automatické přesměrování na kanonickou URL pro danou stránku. V podstatě jde o to že když na stejnou stránku vede více adres tak metoda canonicalize ti zajistí že se všechny přesměrují na jednu.
Mimochodem co je kanonizace v routeru zůstává záhadou pro změnu mně takže mne pouč. ;-)
Editoval enumag (27. 8. 2014 1:11)
- petr.pavel
- Člen | 535
přesměrování na kanonickou url:
Tak to mluvíme o tom samém. Sice to vykonává metoda presenteru ale podle
definic v routeru. Jen jsem si chtěl být jistý, že @matej21
nenavrhoval něco jako
if ($season == $default) $this->redirect()
.
Takže pořád zůstává otázka, jak řešit přesměrovávání při aktuální sezóně, aby mi fungoval $isCurrentLink a aniž bych něco musel prasit v presenterech.
Aby bylo jasno: mě to přesměrování funguje (díky nullování ve FILTER_OUT), jen nefunguje ten $isCurrentLink (tj. nastavení $current v $presenter->createRequest()).
OT: Měli bychom spíš měli říkat kanonikace (canonicalization) než kanonizace (canonization). Aby si to někdo nepletl se svatořečením.
Edit: Koukám, že pár lidí používá kanonikalizace, což dává větší smysl než kanonizace. Kdyby tak existovalo něco pěkně českého.
Editoval petr.pavel (27. 8. 2014 14:26)
- David Matějka
- Moderator | 6445
ne, pouzij defaultni hodnotu, treba takhle:
$router[] = new Route('[<season>/]events/<slug>', array(
'presenter' => 'Tournament',
'action' => 'detail',
'season' => ziskej_defaultni_season(),
));
OT: Měli bychom spíš měli říkat kanonikace (canonicalization) než kanonizace (canonization). Aby si to někdo nepletl se svatořečením.
lol :))
- David Matějka
- Moderator | 6445
@petr.pavel no i kdyz.. wiki mluvi o kanonizaci:
https://cs.wikipedia.org/wiki/Kanonizace_(informatika)
Editoval matej21 (27. 8. 2014 14:41)
- petr.pavel
- Člen | 535
Kanonizace v tomto významu je široce používaný pojem, což ale nemusí
vypovídat o jeho správnosti.
Kanonikaci nikdo nepoužívá (Google nic nenajde), pár lidí (i tady na
fóru) používá kanonikalizace.
Zítra zavolám do Ústavu pro jazyk český a dám vědět.
Jinak díky, pánové, za asistenci a trpělivost.
- Tomáš Votruba
- Moderator | 1114
Škoda, že už to není otázka, ale táhlá diskuse. Teď pro nově příchozí není jasné, jak situaci řešit a budou základát nová témata.
Jestli jste k něčemu došli, mohl bys to Petře nějak zvýraznit (editovat první příspěvek/ztučnit…)?
- petr.pavel
- Člen | 535
Ano, stále nefunguje, ale aspoň už pouze kvůli slugu. Výchozí hodnota pro sezónu funguje a zdá se mi čistší než moje původní úprava ve filtru.
Těžko se mi vyhodnocuje, co je osobní zvyk, dojem programátora, a co
záměr autorů frameworku. V dokumentaci se nepíše, že by
musely být filtry vždy zrcadlové.
Chápu, že to působí pěkně vyrovnaně, což někoho může vést k dojmu,
že to je jediný správný způsob použití. Jestli to tak ale opravdu je,
to nevím.
Souhlasím, že můj způsob řešení slugu v případě, který jsem uvedl, není nejčistší. Mám ale i jiné slugy, třeba profil uživatele:
<?php
$router[] = new Route('players/<id [0-9]+>/<firstNameSlug>-<lastNameSlug>', 'Player:profile');
?>
V presenteru vyhledávám pouze podle id, slugy tam jsou kvůli lidem a SEO.
A je pohodlné vyrábět odkaz pomocí křestního a příjmení v původní
podobě a nestarat se, do čeho jsou převáděny kvůli adrese.
Netvrďte mi, že „správné řešení“ ™ je zde extra položka
v databázi, kterou aktualizuji při přejmenování uživatele, a FILTER_IN,
který podle slugů vrací křestní a příjmení, které nepotřebuji.
V tomto případě naštěstí nepotřebuji zvýrazňovat aktuální stránku, takže debata je čistě akademická.
Editoval petr.pavel (29. 8. 2014 11:25)
- petr.pavel
- Člen | 535
Ač je teď už debata akademická, kdybyste měl někdo chuť poradit, jak „správně“ řešit to url se slugy, které nepotřebuji, tak dejte vědět.
- enumag
- Člen | 2118
Ono v těchto případech je lepší nepředávat do presenteru ani ID ani
slug ale rovnou celou entitu. Tzn. celé to
<id [0-9]+>/<firstNameSlug>-<lastNameSlug>
by byl
jeden parametr. Ve FILTER_IN by sis z toho vyříznul ty čísla na začátku a
vytáhl z db entitu. Ve FILTER_OUT bys pak z té entity ty slugy snadno
poskládal.
EDIT: A ano, reálně to používám jen to nedělám přes ty filtry v routeru ale trochu jinde (což není až tak podstatné).
Editoval enumag (1. 9. 2014 16:11)
- petr.pavel
- Člen | 535
petr.pavel napsal(a):
Kanonizace v tomto významu je široce používaný pojem, což ale nemusí vypovídat o jeho správnosti.
Kanonikaci nikdo nepoužívá (Google nic nenajde), pár lidí (i tady na fóru) používá kanonikalizace.
Zítra zavolám do Ústavu pro jazyk český a dám vědět.Jinak díky, pánové, za asistenci a trpělivost.
Volal jsem, výsledek najdete v diskusi ke stránce na Wikipedii. Tímto vás tam zvu a těším se na připomínky.
Mimochodem, dřív se tu angažoval i náš David, tak můžete kráčet v jeho šlépějích.