Mapping presenteru na Nette 2.3.0

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

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
    • AdminModule
      • presenters
        • HomePresenter
      • SystemModule
        • presenters
          • HomePresenter
      • ShopModule
        • presenters
          • HomePresenter

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

Adresar neni dulezity, dulezity je pouze namespace. Pro AdminModule\SystemModule\HomePresenter je tedy spravne mapovani:

*: *Module\*Presenter
jasin755
Člen | 116
+
0
-

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

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

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

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

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

@DavidGrudl
To, že to už nenačíta PresenterFactory mi nějak uniklo, tím se to vysvětluje a volání construktoru všech presenteru předpokládám je způsobeno tím, že jsou vytvářený pomocí DI. Nebo je to nějaka chyba?

David Grudl
Nette Core | 8172
+
0
-

Co myslíš tím voláním všech konstruktorů?

jasin755
Člen | 116
+
0
-

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

@jasin755 nette pri kompilaci kontejneru zjistuje parametry konstruktoru, aby mohl doplnit zavislosti. Ale instance trid sam nevytvari.

jasin755
Člen | 116
+
0
-

Je to otázka asi přímo na @DavidGrudl, ale co vedlo k tomu presentery řešit přes DI kromě asi nějaké větší čistoty. Pokaždé nějakou reflexi u 40 presenteru zjišťovat co vše potřebuji je dosti pomalé nebo se pletu?

chemix
Nette Core | 1296
+
0
-

Imho: „Pokazde“ = pouze jednou a pak se jede z cache

Filip Procházka
Moderator | 4668
+
0
-

@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
+
+4
-

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)

jasin755
Člen | 116
+
0
-
scanComposer: false
scanDirs: false

tohle jsem nikde nenašel popsany :)

flexroad
Člen | 117
+
0
-

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

Unlink
Člen | 298
+
0
-

Toto závisí na tom, ako máš definované routy.
Kam má smerovať url admin/system?

Podľa chybovej hlášky teraz smeruje na modul admin a system je meno presentera, takže správne hľadá presenter AdminModule\SystemPresenter

yrow
Člen | 12
+
0
-

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

Unlink
Člen | 298
+
0
-

@yrow no môžeš tam pridať routu

$editorRoutes[] = new Route('editor/<module>/<presenter>/<action>[/<id>]', 'Homepage:default');

Editoval Unlink (30. 6. 2015 19:51)

yrow
Člen | 12
+
0
-

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

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)