#1 25. 9. 2009 13:04

David Grudl
Administrator
Registrovaný: 8. 2. 2005
Příspěvky: 4050
Web

[2009–09–25] Adresářová struktura a moduly

Odstraněn jeden dávný pohrobek a úprava adresářové struktury.

Pohrobkové proměnné

Pohrobkem jsou proměnné prostředí:

  • templatesDir – používáno jako proměnná Presenter z Application, nemá co dělat v Environment
  • presentersDir – používáno jako proměnná PresenterLoaderu z Application, nemá co dělat v Environment
  • componentsDir a modelsDir – se v „novodobé historii“ nejspíš nikdy na nic nepoužívalo

Proměnné jsem tedy odstranil, i když z důvodu zpětné kompatibility k proměnným templatesDir a presentersDir metody Presenter::formatLayoutTemplateFiles() a formatTemplateFiles() stále přihlížejí.

Možná zpětná nekompatibilita: pokud vaše aplikace či komponenty tyto proměnné používají. Rychlý workaround je přidat do config.ini:

[common]
variable.templatesDir = %appDir%/templates
variable.presentersDir = %appDir%/presenters
variable.componentsDir = %appDir%/components
variable.modelsDir = %appDir%/models

Moduly

Doporučená adresářová struktura pro moduly je zavádějící a pojmenování jmenných prostorů presenterů v PHP 5.3 nevhodné. Proč?

Především jde o to si uvědomit, co znamená modul. Rozhodně to není (jen) seskupení více presenterů! Základním a vždy přítomným modulem je totiž samotná aplikace (adresář app). Ta obsahuje model, presentery, šablony, komponenty, nebo pravidla routování. A může obsahovat další submoduly, respektive samotná aplikace se může stát (byť po drobné úpravě) submodulem v jiné aplikaci.

Příklad: aplikaci nette.org tak mohu poskládat z modulů wiki + fórum, kde fórum se skládá z modulů frontend a backend.

Stará adresářová struktura tenhle pohled spíš zamlžovala, protože modul nepředstavoval jeden adresář obdobný adresáři app, ale byl roztříštěn do více adresářů. Nová struktura naopak moduly do vlastních adresářů sjednocuje:

app/
        ForumModule/
                model/
                presenters/
                        HomepagePresenter.php (v PHP 5.3 třída ForumModule\HomepagePresenter)
                templates/
        WikiModule
                FrontendModule/
                        ...
                BackendModule/
                        ...
                models/
        temp/
        bootstrap.php

Ve výchozím nastavení se pro šablony používá stará adresářová struktura, nastavením Presenter::$oldModuleMode = FALSE se aktivuje nová adresářová struktura. Třídy presenterů se sice dohledávají jen dle nové adresářové struktury, ovšem RobotLoader je stejně dohledá kdekoliv, takže by se změna neměla projevit. Dále v PHP 5.3 se jako název jmenného prostoru už nepoužívá jen název modulu, ale je doplněn o příponu Module.

Poznámka: jde samozřejmě o vývojovou záležitost a komentáře jsou vítány. Zároveň připomínám, že se bavíme čistě o „doporučené struktuře“, tj. každý můžete používat jakoukoliv jinou strukturu.

Offline

 

#2 25. 9. 2009 13:37

Ondřej Mirtes
Moderator
Místo: Praha
Registrovaný: 8. 1. 2009
Příspěvky: 1357
Web

Re: [2009–09–25] Adresářová struktura a moduly

Nová doporučená adresářová struktura – hezké :) Ale dělá mi starost ta složka models – co když chci jednu třídu využívat ve více modulech? Např. UserModel – ve WebModule slouží např. k registraci uživatelů a v AdminModule k jejich editaci a mazání. Nechtěl bych pro to dělat dvě třídy.

Mimochodem, jak řešíte šablony pro komponenty? Klasika je asi dávat je do /controls/Name/, zkrátka k PHP třídě dané komponenty, ale co kdybych to chtěl mít oddělené? Např. pro to, kdybych měl na hostingu jednu centrální složku pro všechny Nette komponenty, které by využívalo více webů, ale každý by samozřejmě potřeboval vlastní šablonu?

Offline

 

#3 25. 9. 2009 13:57

David Grudl
Administrator
Registrovaný: 8. 2. 2005
Příspěvky: 4050
Web

Re: [2009–09–25] Adresářová struktura a moduly

LastHunter napsal(a):

Nová doporučená adresářová struktura – hezké :) Ale dělá mi starost ta složka models – co když chci jednu třídu využívat ve více modulech? Např. UserModel – ve WebModule slouží např. k registraci uživatelů a v AdminModule k jejich editaci a mazání. Nechtěl bych pro to dělat dvě třídy.

Tomu přece nic nebrání.

Mimochodem, jak řešíte šablony pro komponenty? Klasika je asi dávat je do /controls/Name/, zkrátka k PHP třídě dané komponenty, ale co kdybych to chtěl mít oddělené?

Obvykle do app/components (resp. module/components) dávám komponenty specifické pro konkrétní aplikaci/modul, do libs/components zase komponenty sdílené více weby nebo pro komponenty z repozitáře.

Použití vlastní šablony v komponentě už pak spíš záleží na implementaci komponenty. Takže třeba sdílená komponenta v libs/components má v app/components potomka s vlastní šablonou.

Offline

 

#4 25. 9. 2009 16:04

Ondřej Mirtes
Moderator
Místo: Praha
Registrovaný: 8. 1. 2009
Příspěvky: 1357
Web

Re: [2009–09–25] Adresářová struktura a moduly

OK :) Co lze teď použít namísto templatesDir? Myslel jsem, že tak teď začne fungovat appDir, ale ta mi vede stále pouze do /app/ a ne do /app/WebModule. Potřebuju pro pro určení cesty WebLoaderu.

Offline

 

#5 25. 9. 2009 16:05

edke
Člen
Místo: Kosice
Registrovaný: 22. 9. 2008
Příspěvky: 182

Re: [2009–09–25] Adresářová struktura a moduly

David Grudl wrote:

Především jde o to si uvědomit, co znamená modul. Rozhodně to není (jen) seskupení více presenterů! Základním a vždy přítomným modulem je totiž samotná aplikace (adresář app). Ta obsahuje model, presentery, šablony, komponenty, nebo pravidla routování. A může obsahovat další submoduly, respektive samotná aplikace se může stát (byť po drobné úpravě) submodulem v jiné aplikaci.

Mna by zaujimalo prave to routrovanie. Ako konkretne sa da (ak sa da) v novej strukture rozdelit pre jednotlive moduly ?

Offline

 

#6 25. 9. 2009 16:23

Honza Marek
Moderator
Místo: Kladno
Registrovaný: 31. 3. 2007
Příspěvky: 1281
Web

Re: [2009–09–25] Adresářová struktura a moduly

LastHunter napsal(a):

OK :) Co lze teď použít namísto templatesDir? Myslel jsem, že tak teď začne fungovat appDir, ale ta mi vede stále pouze do /app/ a ne do /app/WebModule. Potřebuju pro pro určení cesty WebLoaderu.

Můžeš si ty proměnné nastavit v configu ostatně jako píše David v úvodním příspěvku.

Offline

 

#7 25. 9. 2009 16:32

David Grudl
Administrator
Registrovaný: 8. 2. 2005
Příspěvky: 4050
Web

Re: [2009–09–25] Adresářová struktura a moduly

edke napsal(a):

Mna by zaujimalo prave to routrovanie. Ako konkretne sa da (ak sa da) v novej strukture rozdelit pre jednotlive moduly ?

Těch možností je víc, jedna taková může počítat s tím, že modul si umí routy vytvořit sám. Bude na to mít třeba továrničku: (jen koncept, psáno z hlavy)

class ForumModule {

public static function createRouter($prefix = 'forum/')
{
        $router = new MultiRouter;
        $router[] = new Route("$prefix<presenter>/<action>", array(
                'module' => 'forum',
                'presenter' => 'Home',
                'action' => 'default',
        );
        $router[] = new Route(...);
        $router[] = new Route(...);
        return $router;
}

}

a pak v bootstrapu:

$application = Environment::getApplication();
$router = $application->getRouter();

// nastavíme vlastní routy aplikace
$router[] = new Route(...);

// připojíme i routy modulů, tj. třeba fóra na extra subdoméně
$router[] = ForumModule::createRouter('//forum.example.com/');

$application->run();

Offline

 

#8 25. 9. 2009 17:09

Panda
Nette guru
Místo: Děčín 32
Registrovaný: 4. 7. 2008
Příspěvky: 386

Re: [2009–09–25] Adresářová struktura a moduly

Osobně používám následující způsob (momentálně je napsaný pro staré rozmístění modulů, fungovat ale bude nezávisle na adresářové struktuře):

Pro každý modul mám třídu, která dědí od abstraktní třídy BaseModule:

<?php
abstract class BaseModule extends Object
{
        public function setupRouter(IRouter $router) { }
        public function setupPermission(SitePermission $permission) { }
        public function setupHooks(SiteHooks $hooks) { }
        // ...
}
?>

V dané třídě překryji požadované metody:

<?php
class PageModule extends BaseModule
{
        public function setupRouter(IRouter $router)
        {
                $router[] = new PageRoute('<uri>', array(
                        'presenter' => 'Page',
                        'action' => 'default'
                ));
        }

        public function setupPermission(SitePermission $permission)
        {
                $permission->addResource('Page');
                $permission->addPrivilege('Page', array('edit', 'create'));
        }

        public function setupHooks(SiteHooks $hooks)
        {
                $hooks->add('Blocks', 'PageModule::blocksEntry');
                $hooks->add('Dashboard/Blocks', 'PageModule::dashboardEntry');
                $hooks->add('AdminMenu', 'PageModule::setupAdminMenu');
        }

        // ...
}
?>

V config.ini mám seznam modulů, které si přeji načíst:

[common]
modules[] = Admin
modules[] = Page
modules[] = News
modules[] = Gallery
modules[] = Article
modules[] = Document

Třída SiteApplication (potomek Application, je nastavený v config.ini jako service pro Nette\Application\Application) mi vše načte a spustí ve správný čas:

<?php
class SiteApplication extends Application
{
        protected $modules;

        /**
         * @var Cache
         */
        protected $cache;

        protected $hooks;


        public function run()
        {
                $this->cache = Environment::getCache('Application');

                $modules = Environment::getConfig('modules');
                foreach ($modules as $module)
                        $this->loadModule($module);

                $this->setupRouter();
                $this->setupHooks();

                // Requires database connection
                $this->onRequest[] = array($this, 'setupPermission');

                // ...

                // Run the application!
                parent::run();

                $this->cache->release();
        }

        protected function loadModule($module)
        {
                $class = $module . 'Module';
                $this->modules[$module] = new $class;
        }

        protected function setupRouter()
        {
                if (Environment::isProduction() && isset($this->cache['router'])) {
                        $this->setRouter($this->cache['router']);
                } else {
                        SiteRoute::initialize();

                        $router = $this->getRouter();
                        // Homepage
                        $router[] = new SiteRoute('<? (index\.(php|html?))?>', array(
                                'presenter' => 'Homepage',
                                'action' => 'default',
                        ), Route::ONE_WAY);

                        // Modules routes
                        foreach ($this->modules as $module)
                                $module->setupRouter($router);

                        // Default route
                        $router[] = new SiteRoute('<presenter>/<action>/<id>', array(
                                'presenter' => 'Homepage',
                                'action' => 'default',
                                'id' => NULL,
                        ));

                        $this->cache->save('router', $router);
                }
        }

        public function setupPermission()
        {
                // ...
        }

        protected function setupHooks()
        {
                if (Environment::isProduction() && isset($this->cache['hooks'])) {
                        $this->hooks = $this->cache['hooks'];
                } else {
                        $this->hooks = new SiteHooks();

                        foreach ($this->modules as $module)
                                $module->setupHooks($this->hooks);

                        $this->cache->save('hooks', $this->hooks);
                }
        }

        // ...
}
?>

Celá moje aplikace je napsaná tak, aby podporovala několik propojených webů běžících na jediné instalaci, takže možnost definovat moduly v rámci sekce config.ini je pro mě klíčová.


Pomůžeš-li jednomu člověku, pomůžeš tím celému světu.
– Talmud

Offline

 

#9 25. 9. 2009 19:18

David Grudl
Administrator
Registrovaný: 8. 2. 2005
Příspěvky: 4050
Web

Re: [2009–09–25] Adresářová struktura a moduly

Panda napsal(a):

Osobně používám následující způsob (momentálně je napsaný pro staré rozmístění modulů, fungovat ale bude nezávisle na adresářové struktuře):

Máš to napsané výborně, v podstatě podobnou cestou půjde vývoj modulů v Nette. Moduly včetně Application budou implementovat IModule. Ještě nevím, jestli to pojmou i jako komponenty. Moduly si budou také určovat vlastní ErrorPresenter.

Offline

 

#10 27. 9. 2009 17:09

sodae
Nette Evangelist
Místo: Rád bych na pláži :)
Registrovaný: 8. 1. 2009
Příspěvky: 219
Web

Re: [2009–09–25] Adresářová struktura a moduly

Jak ale zde řešit když mám několik modulů a jednu administraci jak udělat aby byl jeden globální @layout.phtml pro admina. Struktura je

CoreModule
        - AdminModule
                - presenters
                - templates
                        - @layout.phtml << ten layout globálně pro admina
        - FrontModule
                - presenters, templates
PageModule
        - AdminModule
                - presenters
                - templates (zde bez @layout.phtml a nebo dědit @layout.phtml v CoreModule)
        - FrontModule
                - presenters, templates

doufám že to někdo pochopil, diky


Nette Jabber Room – nette@conf.netlab.cz , všichni jste vítání

Twitter: http://twitter.com/MartinSadovy

Offline

 

#11 27. 9. 2009 17:57

vlki
Nette guru
Registrovaný: 30. 6. 2008
Příspěvky: 239

Re: [2009–09–25] Adresářová struktura a moduly

No, tak uděláš layout v Core a v těch rozšířeních Admina jen něco jako …

{extends '../../CoreModule/AdminModule/@layout.phtml'}

Nebo na tom je něco špatného?:)

Offline

 

#12 27. 9. 2009 18:11

sodae
Nette Evangelist
Místo: Rád bych na pláži :)
Registrovaný: 8. 1. 2009
Příspěvky: 219
Web

Re: [2009–09–25] Adresářová struktura a moduly

To co jsi napsal mě napadlo hned (to jsem ještě nepsal příspěvek) ale otázka jde to zglobalizovat jestli že se jmenuje stejně modul ( = AdminModule) ? Tak jo udělám v AdminBasePresenteru funkci formatLayoutTemplateFiles a hotovo :D


Nette Jabber Room – nette@conf.netlab.cz , všichni jste vítání

Twitter: http://twitter.com/MartinSadovy

Offline

 

#13 28. 9. 2009 12:02

simon
Člen
Registrovaný: 7. 10. 2008
Příspěvky: 173

Re: [2009–09–25] Adresářová struktura a moduly

Zdravim, nova adresarova struktura se mi moc libi a proto jsem si ji implementoval. Nevim si vsak rady s ErrorPresenterem. Predpokladam ze bude mit kazdy modul vlastni. Nevim vsak jak to nastavit. Kdyz dam do bootstrapu

<?php

$application->errorPresenter = 'Error';
$application->catchExceptions = true;

?>

tak mi to nefunguje a zobrazuje se jen bila stranaka. a v logu je

[28-zář-2009 11:57:45] PHP Fatal error: Uncaught exception ‚BadRequestException‘ with message ‚Cannot load presenter 'Portal:Asdfasdf‘, class ‚Portal_AsdfasdfPresenter‘ was not found in ‚/home/simon/Workspace/php/nette/project/baskytara_com/html/../app/PortalModule/presenters/AsdfasdfPresenter.php‘.' in /home/simon/Workspace/php/nette/project/baskytara_com/libs/Nette/Application/Application.php:150 Stack trace: #0 /home/simon/Workspace/php/nette/project/baskytara_com/app/bootstrap.php(108): Application->run() #1 /home/simon/Workspace/php/nette/project/baskytara_com/html/index.php(16): require(‚/home/simon/Wor…‘) #2 {main}

[28-zář-2009 11:58:07] PHP Fatal error: Uncaught exception ‚ApplicationException‘ with message ‚An error occured while executing error-presenter‘ in /home/simon/Workspace/php/nette/project/baskytara_com/libs/Nette/Application/Application.php:181 Stack trace: #0 /home/simon/Workspace/php/nette/project/baskytara_com/app/bootstrap.php(108): Application->run() #1 /home/simon/Workspace/php/nette/project/baskytara_com/html/index.php(16): require(‚/home/simon/Wor…‘) #2 {main}

chapu ze se nedari najit error presenter ale nevim jak to napravit. predem diky

Offline

 

#14 28. 9. 2009 12:16

simon
Člen
Registrovaný: 7. 10. 2008
Příspěvky: 173

Re: [2009–09–25] Adresářová struktura a moduly

Jeste dodam ze problem je tato vyjimka:

Cannot load presenter ‚Error‘, class ‚ErrorPresenter‘ was not found in ‚/home/simon/Workspace/php/nette/project/baskytara_com/html/../app/presenters/ErrorPresenter.php‘.

Na tom umisteni samozrejme presenter neni. Nevim tedy jak nette donutit aby presenter hledalo v adresari s modulem.

Offline

 

#15 28. 9. 2009 18:56

David Grudl
Administrator
Registrovaný: 8. 2. 2005
Příspěvky: 4050
Web

Re: [2009–09–25] Adresářová struktura a moduly

Predpokladam ze bude mit kazdy modul vlastni.

To ano, ale zatím to ještě není implementované. Takže se používá jeden presenter a modul se zapíše pomocí dvojteček $application->errorPresenter = 'Admin:Error';

Offline

 

#16 29. 9. 2009 14:40

Juan
Člen
Registrovaný: 11. 4. 2009
Příspěvky: 55

Re: [2009–09–25] Adresářová struktura a moduly

V souvislosti s adresářovou strukturou obecně bych se chtěl zeptat, kam byste umístili následující:

1. V adresáři libs mám knihovnu Texy. Vytvořil jsem si poděděnou třídu, ve které mám handler pro zvýranění syntaxe pomocí FSHL. Ten rovnou registruji do Texy:

class TexyFshl extends Texy

Vím, že toto by asi šlo přidat třeba do BasePresenteru, ale není nějaké lepší řešení, kam to umístit?

2. Funkce getId a getPath, které používám jako masku pro routování. Kam je dát?

Nehodilo by se mít pro tyto případy v app/ ještě nějakou další složku?

Editoval Juan (29. 9. 2009 14:41)

Offline

 

#17 1. 10. 2009 17:55

Juan
Člen
Registrovaný: 11. 4. 2009
Příspěvky: 55

Re: [2009–09–25] Adresářová struktura a moduly

Nic? Tak se zeptám ještě jinak… Např. do které složky je nejvhodnější umístit vlastní router?

Offline

 

#18 1. 10. 2009 19:22

Honza Kuchař
Moderator
Místo: Brno
Registrovaný: 12. 8. 2007
Příspěvky: 1285
Web

Re: [2009–09–25] Adresářová struktura a moduly

To záleží čistě na tobě.

Třeba si vytvoř novou složku v app/ nebo do libs/. Nette tě nijak neomezuje.

Offline

 

#19 2. 10. 2009 0:09

kravčo
Moderator
Místo: Bratislava
Registrovaný: 15. 6. 2008
Příspěvky: 564

Re: [2009–09–25] Adresářová struktura a moduly

Napríklad ja mám vlastné routre v adresári app/routers. Pokiaľ používaš RobotLoader so štandardným nastavením %appDir% + %libsDir%, tak ich natiahne sám, ak ho nepoužívaš, tak ich načítaj ručne…

Offline

 

#20 2. 10. 2009 12:10

Juan
Člen
Registrovaný: 11. 4. 2009
Příspěvky: 55

Re: [2009–09–25] Adresářová struktura a moduly

Díky, přesně tak to používám. Jen mi šlo o to, jestli je to ona „Best Practise“…

Offline

 

#21 22. 10. 2009 19:58

na1k
Člen
Registrovaný: 18. 2. 2008
Příspěvky: 103
Web

Re: [2009–09–25] Adresářová struktura a moduly

Po nějaké době jsem updatoval na novou dev revizi a s tím jsem i přeorganizoval adresáře podle prvního Davidova postu. Jenže se mi něco pokazilo, protože se mi namísto celé stránky vykreslí jen šablona aktuálního view. Chybí tedy celý @layout. Netušíte někdo co je špatně? soubor s layoutem mám v app\FrontModule\templates\@layout.phtml

Offline

 

#22 22. 10. 2009 20:25

Ondřej Mirtes
Moderator
Místo: Praha
Registrovaný: 8. 1. 2009
Příspěvky: 1357
Web

Re: [2009–09–25] Adresářová struktura a moduly

na1k napsal(a):

Po nějaké době jsem updatoval na novou dev revizi a s tím jsem i přeorganizoval adresáře podle prvního Davidova postu. Jenže se mi něco pokazilo, protože se mi namísto celé stránky vykreslí jen šablona aktuálního view. Chybí tedy celý @layout. Netušíte někdo co je špatně? soubor s layoutem mám v app\FrontModule\templates\@layout.phtml

Nový systém počítá s tím, že používáš „nové šablony“ – s makry {block} a {extends}. Doporučuji shlédnout přednášku: http://blip.tv/file/2514636

Offline

 

#23 22. 10. 2009 20:37

na1k
Člen
Registrovaný: 18. 2. 2008
Příspěvky: 103
Web

Re: [2009–09–25] Adresářová struktura a moduly

Paráda, děkuju, nějak mi nedošlo, že v nové revizi už tyhle šablony budou :)

Offline

 

#24 1. 11. 2009 11:56

Jerry123456789
Člen
Registrovaný: 29. 12. 2008
Příspěvky: 37

Re: [2009–09–25] Adresářová struktura a moduly

Šmankote, jak tak koukám na Pandův příklad komplexní aplikace, zjišťuju že se mám eště dst co učit :D

Ale chtělo by to nějaký howto na komplexitu, tohle bych vymejšlel dlouho. Taky by mě zajímalo třeba když máš třídu *Module jak to zapasuješ do MVP? Nebo jsou moduly (*Module, ne adresář) jen na router/permissions…?


42

Offline

 

#25 12. 11. 2009 14:55

HosipLan
Člen
Místo: Pálava
Registrovaný: 1. 6. 2009
Příspěvky: 118
Web

Re: [2009–09–25] Adresářová struktura a moduly

Zdravim, zalíbil se mi Pandův přístup. Něco takového jsem chtěl udělat, ale nevěděl jsem jak přidat další vrstvu do životního cyklu, takže nápad zaregistrovat si vlastní třídu pro Application je parání!

Bohužel jsem nedokázal pochopit jaký význam mají tvoje ‚Hooks‘ v modulech, snažim se nato přijit už dva týdny ale furt jsem nic nevymyslel :( kdyby ses mohl ještě trochu rozepsat o tom tvém příkladu byl bych ti myslím nejenom já vděčný :)


Nette Jabber Room – nette@conf.netlab.cz , všichni jste vítáni

Offline

 

Zápatí