Nefunkční Environment::getHttpRequest()->setUri()

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

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

Ta metoda byla odstraněna v revizi 33, kdy se některé metody z Uri přesunuly do nové třídy UriScript.

Osobně si moc nedokážu představit, jaké by volání této metody mělo význam v praxi. K čemu to konkrétně mělo sloužit?

Mas3r
Člen | 116
+
0
-

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

Panda
Člen | 569
+
0
-

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)

Mas3r
Člen | 116
+
0
-

Aha, vidíš, tady to řešení s routou, kde je jen alias me vůbec nenapadlo…

Zkusím, uvidím… díky

David Grudl
Nette Core | 8147
+
0
-

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

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.

Mas3r
Člen | 116
+
0
-

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í?

Editoval Mas3r (14. 8. 2008 15:18)

ViliamKopecky
Nette hipster | 230
+
0
-

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

Mas3r
Člen | 116
+
0
-

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

Editoval Mas3r (14. 8. 2008 16:21)

Panda
Člen | 569
+
0
-

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

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

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

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

Mas3r
Člen | 116
+
0
-

Okej, zkusím :)