Nefunkční Environment::getHttpRequest()->setUri()
- Mas3r
- Člen | 116
Ahoj, tak jsem po delší době upgradnul na novější verzi. Bohužel mi v bootstrap.php nefunguje volání Environment::getHttpRequest()->setUri( new Uri($neco) )
Nevíte jak na to? :)
Ještě Laděnka:
MemberAccessException
Call to undefined method HttpRequest::setUri().
:-D
Editoval Mas3r (12. 8. 2008 8:43)
- Panda
- Člen | 569
Mas3r napsal(a):
K Aliasům :) z /nova-strana to přesměrovalo na /module/presenter/view/54 například :) možná jsem to dělal zbytečně komplikovaně a existuje lepší způsob… :)
BTW: Jak tedy řešíte URL? Neříkejte, že máte všude /module/presenter/view nebo desítky Rout
Osobně to dělám přes routy stranka/<uri>
,
clanek/<uri>
, kategorie/<uri>
… Pokud by
však bylo potřeba víc rout, než je zdrávo, tak není problém routy napsat
třeba nějak takto:
<?php
$router[] = new Route('<alias>', array(
'presenter' => 'Alias',
'action' => 'default',
'alias' => 'uvodni-stranka',
));
$router[] = new Route('system/<module>/<presenter>/<action>/<id>', array(
'module' => 'Default',
'presenter' => 'Default',
'action' => 'default',
'id' => NULL,
));
?>
U těch automaticky generovaných linků by nemělo jedno slovíčko na
začátku vadit (popř. je možné u té routy vynutit uvedení module a
presenter, pak tam to počáteční system/
(nebo cokoliv jiného,
co by vystihovalo myšlenku) nemuselo být). AliasPresenter
by ve
view default
hledal vhodný alias a případně dál forwardoval na
příslušný module/presenter/view.
Trochu problémem by však byl zpětný překlad na správnou routu, Nette by
s pomocí výchozích objektů nedokázalo určit, zda má daný
module/presenter/view nějaký alias. To by ale šlo udělat rozšířením
třídy Route
tak, aby s aliasy počítala. Doporučuji podívat
se na metody constructUrl
ve třídách MultiRouter
a
Route
.
Dalším řešením je napsání i vlastního Routeru, který by s aliasy
počítal, a pokud by žádný nenašel, tak by vše předal svému rodiči
MultiRouter
.
Vše je to jen o správném návrhu, chce to trochu zapřemýšlet a najít řešení, které je vhodné pro konkrétní aplikaci. Univerzální řešení se hledá velice těžko.
Editoval Panda (12. 8. 2008 11:20)
- David Grudl
- Nette Core | 8218
Cestou Aliasu bych určitě nešel, jak správně Panda píše, problém bude se zpětným překladem. Také se míchají vrstvy routování a presentování, což je proti čistotě návrhu (no já vím, čistota není vše, nýbrž jen půl zdraví ;)
- Mas3r
- Člen | 116
<?php
$httpRequest = Environment::getHttpRequest();
$uri = str_replace($httpRequest->getUri()->basePath, '', $httpRequest->getUri()->path);
$alias = dibi::query("SELECT redir FROM [:cms:aliases] WHERE uri=%s LIMIT 1", $uri);
$alias = $alias->fetchSingle();
if( $alias != '' ) {
$aliasArray = explode('/',$alias);
foreach($aliasArray as $a) {
$route[] = ucfirst($a);
}
$router[] = new Route(
'<alias>',
array(
'module'=>$route[0],
'presenter'=>$route[1],
'action'=>$route[2],
'id'=>$route[3],
)
);
?>
Ale samozřejmě pak nelze použít link() v nette, ale přímo <a href=„alias“>Alias</a> :)
Stránky se otvírají, takže až budu mít čas, tak ještě otestuju víc, ale určite nepůjde link() ,že… :)
- David Grudl
- Nette Core | 8218
Nerozumím, proč to děláš takto složitě? I na webech s hodně složitou strukturou URL si vystačím s cca 10 routama max.
- ViliamKopecky
- Nette hipster | 230
Mas3r napsal(a):
Např shop:
- example.com/notebooky/15-palcu
- example.com/super-pocitac-pentium
Nebo stránka
- example.com/o-nas
Jak vyřešit to routování?
Musíš si to představit v logický struktuře.
o-nas
bude zřejmě stránka se statickým obsahem. Můžeš
mít třeba ONasPresenter
, což ti bude při základní routě
<presenter>/<action>/<id>
sedět. Nebo můžeš
mít HomepagePresenter
který má view ONas
, pak si
budeš muset přidat routu <action>
s nastaveným
presenterem Homapage
, čili
<?php
$router[] = new Route('<action>', array(
'presenter' => 'Homepage',
'action' => 'default',
));
?>
example.com/notebooky/15-palcu – Pravděpodobně CathegoryPresenter
<?php
$router[] = new Route('<cat_id>/<neco>', array(
'presenter' => 'Cathegory',
'action' => 'default',
'neco' => null,
));
?>
example.com/super-pocitac-pentium – to nevim co by mělo ukazovat, ale zase ti to představuje nějakou logickou jednotku, zřejmě ProductPresenter
- Panda
- Člen | 569
Mas3r napsal(a):
Díky, to ještě chápu, ale jak Router pozná toto:
example.com/o-nas vs. example.com/notebooky
to prvni je stránka uložená v DB a její odkaz je v menu a to druhé je kategorie e-shopu
To nepozná, musíš URL navrhnout tak, aby to bylo jednoznačné: example.com/o-nas a example.com/kategorie/notebooky. A pokud chceš, aby to poznal, napiš si vlastní router.
- Mas3r
- Člen | 116
Tak mi to nedalo a zkusil jsem hrábnout do Presenter.php :)
<?php
protected function constructUrl($request)
{
$uri = $this->router->constructUrl($request, $this->httpRequest);
/*Podpora Aliasů*/
$uri = str_replace($this->httpRequest->getUri()->basePath, '', $uri);
$alias = dibi::query("SELECT uri FROM [:cms:aliases] WHERE redir=%s LIMIT 1", $uri);
$alias = $alias->fetchSingle();
if($alias!='') $uri = $alias;
/*Podpora Aliasů*/
if ($uri === NULL) {
$presenter = $request->getPresenterName();
$params = $request->params;
$view = $params['action'];
unset($params['action']);
$params = urldecode(http_build_query($params, NULL, ', '));
throw new InvalidLinkException("No route for $presenter:$view($params)");
}
//return $this->getAjaxDriver()->link($uri);
return $uri;
}
?>
Mno a teď už se generuje i URL :) Ještě nevím, zda to bude nějak funkční, ale při zavolání
<?php
$control->link(':pages:view:default', 2);
?>
to vrátí příslušný alias :) A teď mi nadejte :-D A mám ještě jednu hloupou otázku.. Dá se vytvořit nějak vlastní metoda, která se bude volat místo te v Presenter.php, abych nemusel zasahovat do Nette?
- Panda
- Člen | 569
Mas3r napsal(a):
Dá se vytvořit nějak vlastní metoda, která se bude volat místo te v Presenter.php, abych nemusel zasahovat do Nette?
Jo, dáš jí do nějaké jiné třídy, která bude dědit od
Presenter
a všechny Tvé presentery budou dědit od ní. Zpravidla
to bývá BasePresenter
.
Nebo to můžeš udělat tak, jak říkám celou dobu: napíšeš si vlastní
router – na začátku Presenter::constructUri
se volá metoda
constructUri
routeru, takže toho můžeš využít a hledání
aliasů můžeš přesunout tam. Navíc můžeš překrýt i metodu
match
tak, aby před procházením rout koukla do aliasů. Novou
třídu pak musíš nastavit jako ‚service‘ v config.ini
:
service.Nette-Application-IRouter = MyRouterWithAliasesSupport
- David Grudl
- Nette Core | 8218
Jak správně píše Panda, přesuň tuto logiku z Presenter::constructUrl do MyRouter::contructUrl, potomka SimpleRouter.
Pokud nepoužíváš config.ini
nebo preferuješ imperativní
styl programování, můžeš router nastavit takto:
$application->setRouter(new MyRouter)
. Vlastně lze použít
i klasické: $application->router[] = new MyRouter