Jednoduchý seorouter nemá přístup k instanci třídy z modelu
- argosovo
- Člen | 54
Ahoj,
snažím se nastavit seo routování podle db (název firmy místo ID do
adresy) – co nejjednodušeji, pro začátek, bez zbytečných tříd navíc,
přes to, to začíná být pěkně složité (konstruováno podle přednášky
https://www.youtube.com/watch?… a možná něco málo ze
zdejší diskuze):
- zjistil jsem, že musím vytvořit novou routu v bootstrap.php:
<?php
$firmy=$container->firmy;
$router[] = new Model\BazarRoute('bazar/<bazar>',array(
'module'=>'Front',
'presenter'=>'Inzeraty',
'action'=>'bazar',
'bazar'=>array(0=>array(
Route::FILTER_IN => function($bazar) use ($container){
if(is_numeric($bazar)){
return $bazar;
}
else{
return $firmy->getIdBySeo($bazar);
}
},
Route::FILTER_OUT =>function($bazar) use ($container){
if(!is_numeric($bazar)){
return $bazar;
}else{
return $firmy->getSeoById($bazar);
}
}
)
),$firmy));
?>
- pro tuto routu jsem tedy vytvořil novou třídu BazarRoute:
<?php
class BazarRoute extends \Nette\Application\Routers\Route{
private $firmy;
public function __construct($mask, $metadata = array(), $flags = 0,\Model\AdminModule\Firmy $firmy){
parent::__construct($mask, $metadata = array(), $flags = 0);
$this->firmy=$firmy;
}
public function injectUsersModels(\Model\AdminModule\Firmy $firmy)
{
$this->firmy=$firmy;
}
public function match(\Nette\Http\IRequest $request){
$appRequest = parent::match($request);
if(!is_numeric($appRequest->parameters['bazar'])){
$page = $this->firmy->getIdBySeo($appRequest->parameters['bazar']);
if($page==NULL){
return NULL;
}
$appRequest->parameters['bazar']=array(0=>$page);
}
return $appRequest;
}
}
?>
(zbytek je ozkoušený že funguje, tedy nebudu uvádět)
v configu mám
<?php
services:
firmy: Model\AdminModule\Firmy
?>
Nová třída BazarRoute přesto nemá přístup k \Model\AdminModule\Firmy
$firmy (chyba Call to a member function getIdBySeo() on
null) – nepomáhá construct, nepomáhá inject. Podle toho co jsem
vyčetl: ve chvíli kdy žádám instanci této třídy při vytváření
BazarRoute, tak třída ještě není zavedena, zavede se až později.
Nicméně ve filtrech při vytváření této BazarRoute už mám tu samou
třídu dostupnou a vrátí správná data (jelikož parametry v této metodě
se spouští asi později). Dokonce u mě nefunguje ani předání hodnoty tak
jako na videu – tedy přes context (nebo jde o to že nepředávám
databázi, měl jsem dojem, že bude třída jako třída a raději bych
předával nějakou vyšší třídu). Takže fajn, instance není v této
chvíli vytvořena, ale tím jsem se zasekl na mrtvém bodě pročítajíc
diskuze pořád dokola(včetně https://forum.nette.org/…jeni-v-route
kde Filip Procházka myslím radí jak na to – nicméně po realizaci jsem
měl o jednu třídu (tedy v začátku potenciální problém) navíc a stále
neexistující instanci). Poradí někdo jak dostat instanci třídy z modelu
do třídy která vytváří Route()?
Edit
Něco jsem přehlédl a dle přednášky to vypadá, že to funguje… Nicméně
i z té přenášky vyplývá, že tohle není úplně košér řešením
tkaže jak je to správně?
Děkuji
Editoval argosovo (22. 9. 2015 17:43)
- Darkling
- Člen | 35
Ahoj, routy nevytvarej přímo v bootstrap, ale v nějaké jiné třídě
RouterFactory, do té třídy si pak můžeš snadno předávat závislosti
přes konstruktor. Inspiraci můžeš najít v nette sandbox viz odkaz dole,
jenom ji pak nezapomeň zaregistrovat v configu opět viz nette sandbox.
https://github.com/…rFactory.php
- argosovo
- Člen | 54
Děkuji za rady, článek jsem přečetl a zjistil nějaké užitečné
informace, nicméně nejdříve jsem se vydal cestou vytvoření vlastního
routeru, upravil jsem defaultní router factory tak, že mé routy se
načítají tam.
Co nefunguje a pořád nechápu, jak docílit aby fungovalo, je načítání
jiných tříd z modelu do této RouterFactory. Vše funguje dokud nevytvořím
konstruktor:
<?php
namespace App;
use Nette,
Nette\Application\Routers\RouteList,
Nette\Application\Routers\Route,
Nette\Application\Routers\SimpleRouter;
class RouterFactory
{
/**
* @return \Nette\Application\IRouter
*/
public function __construct(){
}
public function createRouter()
{
$router = new RouteList();
/* $bazarRoute=new \Model\BazarRoute('bazar/<bazar>',array(
'module'=>'Front',
'presenter'=>'Inzeraty',
'action'=>'bazar',
'bazar'=>array(0=>array(
Route::FILTER_IN => function($bazar) use ($container){
if(is_numeric($bazar)){
return $bazar;
}
else{
return $firmy->getIdBySeo($bazar);
}
},
Route::FILTER_OUT =>function($bazar) use ($container){
if(!is_numeric($bazar)){
return $bazar;
}else{
$firmy=$container->firmy;
return $firmy->getSeoById($bazar);
}
}
)
)));*/
$router[] = new Route('<presenter>/<action>/<id>', array(
'module' => 'Front',
'presenter' => 'Homepage',
'action' => 'default',
'id' => NULL,
));
return $router;
}
}
?>
pro úplnost (z bootstrapu zmizelo úplně vše co se routeru týká) a
v configu mám:
<?
services:
router: App\RouterFactory::createRouter
?>
vyhodí mi to error: Type of service ‚routing.router‘ is
unknown.
Přemýšlel jsem, zda třeba RouterFactory nemá něco dědit, implementovat
atp., takže po různých pokusech, je výsledek stále stejný… jakmile
konstruktor odeberu vše začne zase fungovat…
jenže pokud nevytvořím konstruktor, neumím třídě předat instanci Třídy
která překládá seo->id a zpět. Jak na to?
- David Matějka
- Moderator | 6445
ten phpdoc blok s @return
musi byt nad metodou createRouter, ne
nad konstruktorem
- argosovo
- Člen | 54
Děkuji moc, už to funguje… je k tomu někde nějaká vysvětlivka, proč php poznámka ovlivňuje chování celého frameworku?
Mám pocit, že jsem tak půl roku zpátky četl něco o injection pomocí
poznámky a že to i fungovalo, nicméně tady se nic neinjektuje, pouze
označuje co se vrátí a přes to to má vliv…
Ještě jednou děkuji všem
- Unlink
- Člen | 298
Ono to nieje poznámka, tie sú v php pomocou // a /* */
Tamto sa volá dokumentačný komentár (je v tom rozdiel, pretože
dokumentačné komentáre je možné čítať aj v kode)
PHP je jazyk aký je, (do verzie 7) nemá return typy, to znamená že php ti priamo neposkytuje možnosť zistiť čo vráti volanie nejakej funkcie / metódy. V php sa toto rieši spracovávaním dokumentačných komentárov (nette/reflection).
Nette využíva dependency injection a keď napríklad registruješ ten router do kontajnera nejako takto
router: @petrjirasek\Routers\RouterFactory::createRouter
tak mu vlastne povieš že chceš mať službu s názvom router, ktorú
vyrobí tak že zavolá createRouter
ale nikde mu tu nehovoríš
akého typu bude tá služba. On si podľa toho komentáru zistí že to bude
typu
\Nette\Application\IRouter
- David Matějka
- Moderator | 6445
Jeste doplnim, ze ty phpdoc nejsou v tomto pripade povinny, ale zjednodusuji nasledny zapis v neonu, bez nich bych musel zapsat:
router:
create: @Foo\Bar\RouterFactory:createRouter
class: Nette\Application\IRouter
- Azathoth
- Člen | 495
běžné komentáře číst nejde, ale když máš phpdoc, tedy začátek komentáře je /**, a uvnitř toho phpDocu začíná komentář zavináčem, je to anotace a ta se běžně používá v php. zde je slideshare o anotacích , tady je ukázka, jak je číst přes reflexi a Doctrine/Annotations poskytují asi nejmocnější nástroje pro práci s anotacemi v php