Mapping presenteru na Nette 2.3.0
- jasin755
- Člen | 116
Zdraívm,
mám dotaz Nette mi přestalo od verze 2.3.0 načítat presentery v modulech a
submodulech.
Struktura je následující:
- app/
- FrontModule
- presenters
- HomePresenter
- …
- presenters
- AdminModule
- presenters
- HomePresenter
- …
- SystemModule
- presenters
- HomePresenter
- …
- presenters
- ShopModule
- presenters
- HomePresenter
- …
- presenters
- presenters
- FrontModule
v configu mám nastavený mapping následovně:
nette
application:
mapping:
*: *Module\presenters\*Presenter
pro autoload používám composer. Namespace jsou v tomto tvaru:
namespace AdminModule\SystemModule;
class HomePresenter extends BasePresenter {
...
}
Do teď s tím nebyl problém, tak tomu moc nerozumím kde je najednou chyba.
Edit:
Samozřejmě se dá udělat do composeru classmap:
[„app/AdminModule“,„app/FrontModule“], ale nepříjde mi to jako dobré
řešení, načítají se mi pak všechny presentery i ty co se nepouživají
v daný okamžik.
Děkuji za rady.
Editoval jasin755 (10. 3. 2015 15:36)
- David Matějka
- Moderator | 6445
Adresar neni dulezity, dulezity je pouze namespace. Pro
AdminModule\SystemModule\HomePresenter
je tedy spravne
mapovani:
*: *Module\*Presenter
- jasin755
- Člen | 116
Zkusil jsem a bez úspěchu.
Radši přikládám obsah composeru ještě:
{
"repositories" : [{
"type" : "vcs",
"url" : "https://github.com/jasin755/gettext.git"
}],
"require" : {
"nette/nette" : "2.3.0",
"kdyby/doctrine" : "~2.0",
"jasin755/gettext" : "~1",
"jkuchar/pdfresponse" : "dev-master",
"jms/serializer" : "dev-master",
"doctrine/search" : "dev-master",
"ruflin/Elastica" : "dev-master"
},
"autoload" : {
"psr-0" : {
"Exsys\\" : "app/Model",
"Nella\\" : "app/Model",
"Extractor\\" : "app/Model"
}
}
}
- David Matějka
- Moderator | 6445
A co to hlasi za chybu?
mimochodem
Samozřejmě se dá udělat do composeru classmap: [„app/AdminModule“,„app/FrontModule“], ale nepříjde mi to jako dobré řešení, načítají se mi pak všechny presentery i ty co se nepouživají v daný okamžik.
neni pravda – to pouze vytvori classmapu a nacita to pri pozadavku na tridu. A proc pouzivas composer autoloader? V nette je robotloader ;)
- jasin755
- Člen | 116
Chyba je klasická:
Cannot load presenter 'Admin:System:Products', class 'AdminModule\SystemModule\ProductsPresenter' was not found.
@DavidMatějka
neni pravda – to pouze vytvori classmapu a nacita to pri pozadavku na tridu.
to jsem si myslel, ale v tom případě nechápu proč to volá construktory všech presenteru dokonce i v CLI, ktery má zvášť bootstrap, který nejde ani přes router.
@DavidMatějka
A proc pouzivas composer autoloader? V nette je robotloader ;)
Protože, ten composer musíš použít tak či tak. Jinak by si nevytvořil instanci ani samotného RobotLoaderu, teda pokud si ho ručne neincludneš.
Editoval jasin755 (10. 3. 2015 15:57)
- David Matějka
- Moderator | 6445
Ale composer autoloader neni tak chytry jako robotloader. Kdyz neexistuje
trida, robotloader se ji pokusi najit i v runtime tim, ze znovu proskenuje
dane adresare. composer class map se musi rucne aktualizovat pomoci
composer dump-autoload
.
Ja pro vyvoj pouzivam robot loader (abych prave nemusel porad rucne aktualizovat autoloader composeru) a na produkci pak vse ridi composer.
- David Grudl
- Nette Core | 8172
A podle čeho soudíš, že ti to Composer načítá? Kdyby načítal, tak nebudeš mít chybovou hlášku, že třída nebyla nalezena. A jak by to vůbec mohl načítat, když mu ten classmap neuvedeš?
Ve verzi 2.2 ti to načítal PresenterFactory. Ten už to nedělá, tak buď to nech na Composeru (ale je mu potřeba nastavit classmap a ručně pokaždé aktualizovat) nebo na RobotLoaderu (nejsnadnější cesta).
- jasin755
- Člen | 116
@DavidGrudl
V construktorech presenteru mám nějaké závislosti na ruzných fasádách a
některé presentery nebyli dodělané a měli v construktoru např. špatný
namespece k fasádě nebo vyžadovali instanci, která už neexistuje.
A např. když zobrazuji FrontModule/LoginPresenter tak mi to hodí vyjímku na
AdminModule/SystemModule/ProductPresenter. Dělá to v CLI, kde ani
nepoužívám router a vůbec s presentery nepracuji.
- David Matějka
- Moderator | 6445
@jasin755 nette pri kompilaci kontejneru zjistuje parametry konstruktoru, aby mohl doplnit zavislosti. Ale instance trid sam nevytvari.
- Filip Procházka
- Moderator | 4668
@jasin755 není to zrovna nejrychlejší, ale je to právě věc, která se děje pouze jednou a to v momentě kdy se kontejner kompiluje. Když je už zkompilovaný, tak už se žádná taková analýza neprovádí. Tedy je to napak rychlejší než do teď, protože do teď se to vždy znovu analyzovalo dynamicky, při každém vytvoření instance presenteru.
- David Matějka
- Moderator | 6445
Je problem, ze pri vyvoji kazda zmena v presenteru vyvola kompilaci kontejneru – coz je pomale. Ja mam pro dev v configu:
application:
scanComposer: false
scanDirs: false
Editoval David Matějka (10. 3. 2015 19:45)
- flexroad
- Člen | 117
Ahoj,
resim presne to co @jasin755 pred 4mi mesici…
Muzete mi nekdo poslat ukazku routeru, ktery ten vyse uvedeny priklad zprovozni?
Pokud pouziju vyse uvedeny priklad spolu s mapovanim „*: *Module*Presenter“, vse mi funguje az do chvile kdy chci nejaky podadresar, tzn.:
http://www.server.com/
← funguje
http://www.server.com/admin ← funguje
http://www.server.com/admin/system ← NEFUNGUJE a
vraci chybu:
Cannot load presenter ‚Admin:System‘, class ‚AdminModule\SystemPresenter‘, was not found
DIKY ZA COKOLIV!!!
@flexroad
- yrow
- Člen | 12
snad to nějak pomůže. mám podobnou adresářovou strukturu se submoduly
config mapping:
<?php
application:
errorPresenter: Error
mapping:
*: App\*Module\Presenters\*Presenter
?>
routing:
<?php
$router = new RouteList();
$router[] = $editorRoutes = new RouteList('Editor');
$editorRoutes[] = new Route('editor/<presenter>/<action>[/<id>]', array(
'presenter' => 'Homepage',
'action' => 'default'
));
$router[] = $frontRoutes = new RouteList('Front');
$frontRoutes[] = new Route('<presenter>/<action>[/<id>]', array(
'presenter' => 'Homepage',
'action' => 'default'
));
return $router;
?>
používám absolutní linky:
<?php
//editor homepage
<a n:href=":Editor:Homepage:default" class="logo">
// odkaz na presenter v app/EditorModule/presenters/AdminSettingsPresenter.php
<a n:href=":Editor:AdminSettings:default">
// odkaz na submodul v app/EditorModule/PagesModule/presenters/DefaultPresenter.php
<a n:href=":Editor:Pages:Default:default">
?>
až na to že url toho posledního linku se submodulem je
/editor/pages.default/
za tečkou je presenter, což mi nevadí. hlavně že to nějak funguje
- yrow
- Člen | 12
Unlink napsal(a):
@yrow no môžeš tam pridať routu
$editorRoutes[] = new Route('editor/<module>/<presenter>/<action>[/<id>]', 'Homepage:default');
to jsem zkoušel
, v tomto případě stačí zadat
/editor/pages/
a najde to /app/EditorModule/PagesModule/presenter/DefaultPresenter.php
ale když dám
/editor/admin-settings/
tak to hledá
/app/EditorModule/AdminSettingsModule/presenter/DefaultPresenter.php
přestože chci /app/EditorModule/presenters/AdminSettingsPresenter.php
v tomto případě neví, jestli má šáhnout do specifickýho presenteru v modulu nebo do defaultního presenteru v submodulu i když tu routu dávám na různá místa, vždy to akceptuje první a druhá je may
možná by se to dalo řešit pres <submodule> + úprava mappingu + submoduly ve složkách alá PagesSubmodule/presenters
- Unlink
- Člen | 298
Ono by asi trebalo vypísať všetky tie submoduly pokiaľ to chceš kombinovať.
$router = new RouteList();
$router[] = $editorPahesRoutes = new RouteList('Editor:Pages');
$editorPahesRoutes [] = new Route('editor/pages/<presenter>/<action>[/<id>]', array(
'presenter' => 'Homepage',
'action' => 'default'
));
$router[] = $editorRoutes = new RouteList('Editor');
$editorRoutes[] = new Route('editor/<presenter>/<action>[/<id>]', array(
'presenter' => 'Homepage',
'action' => 'default'
));
$router[] = $frontRoutes = new RouteList('Front');
$frontRoutes[] = new Route('<presenter>/<action>[/<id>]', array(
'presenter' => 'Homepage',
'action' => 'default'
));
return $router;
alebo to zjednodušiť tým, že vymenuješ tie povolené moduly
$editorRoutes[] = new Route('editor/<module submodul1|submodul2>/<presenter>/<action>[/<id>]', 'Homepage:default');
$editorRoutes[] = new Route('editor/<presenter>/<action>[/<id>]', 'Homepage:default');
a v tomto prípade
editor/submodul1
→ pôjde na default presenter submodulu1
ale
editor/nemodul
→ pôjde na presenter nemodul
a treba to definovať tak, že najskôr dáš tu routu pre submoduly a potom tu všeobecnú
Editoval Unlink (1. 7. 2015 18:11)