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

před 9 lety

David Grudl
founder | 6753
+
0
-

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.

před 9 lety

Ondřej Mirtes
Člen | 1539
+
0
-

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?

před 9 lety

David Grudl
founder | 6753
+
0
-

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.

před 9 lety

Ondřej Mirtes
Člen | 1539
+
0
-

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.

před 9 lety

edke
Člen | 198
+
0
-

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 ?

před 9 lety

Honza Marek
Člen | 1674
+
0
-

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.

před 9 lety

David Grudl
founder | 6753
+
0
-

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();

před 9 lety

Panda
Člen | 570
+
0
-

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á.

před 9 lety

David Grudl
founder | 6753
+
0
-

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.

před 9 lety

sodae
Nette Evangelist | 251
+
0
-

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

před 9 lety

vlki
Člen | 218
+
0
-

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?:)

před 9 lety

sodae
Nette Evangelist | 251
+
0
-

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

před 9 lety

simon
Člen | 98
+
0
-

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

před 9 lety

simon
Člen | 98
+
0
-

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.

před 9 lety

David Grudl
founder | 6753
+
0
-

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';

před 9 lety

Jan Jakeš
Člen | 178
+
0
-

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)

před 9 lety

Jan Jakeš
Člen | 178
+
0
-

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

před 9 lety

Honza Kuchař
Člen | 1647
+
0
-

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

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

před 9 lety

kravčo
Člen | 723
+
0
-

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…

před 9 lety

Jan Jakeš
Člen | 178
+
0
-

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

před 9 lety

na1k
Člen | 289
+
0
-

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

před 9 lety

Ondřej Mirtes
Člen | 1539
+
0
-

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

před 9 lety

na1k
Člen | 289
+
0
-

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

před 9 lety

Jerry123456789
Člen | 37
+
0
-

Š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…?

před 9 lety

Filip Procházka
Moderator | 4693
+
0
-

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ý :)

před 9 lety

Panda
Člen | 570
+
0
-

Nazdar,
moje hooks jsou tak trochu inspirovány hooky v Drupalu (principem, ne realizací – Drupal není psán objektově). Tam slouží k tomu, aby modul mohl ovlivnit všechno možné, od nových typů obsahu, přes existující formuláře až po různá interní zpracování vložených dat a tak podobně.

Tak daleko, jako jde Drupal, jsem ale nešel. Moje hooky používám na občasné ovlivnění určitých prvků webu, například jako hlavní stránku administrační sekce mám nástěnku. Ta je bez modulů prázdná, naplní se právě až pomocí těch modulů – modul si zaregistruje na hook funkci (používám statické funkce, abych mohl jednoduše cachovat, ačkoliv to není z hlediska objektového návrhu úplně ideální), té funkci se předá objekt (Hashtable) s aktuálním seznamem bloků a jen do tohoto objektu přidá záznam. Pak až je potřeba sestavit seznam těchto bloků, tak se jen projde pole takto zaregistrovaných funkcí, zavolají se a seznam bloků na nástěnce je na světě.

Další použití, které je v kódu vidět, je sestavování administračního menu. Zaregistrovaná funkce opět přidává do objektu záznam, popř. sadu záznamů. Další využití, které v kódu vidět není a které ještě nemám napsané, by byl modul komentářů. Tam by se registroval hook, který by modifikoval formulář na přidávání článku/novinky/galerie – přidal by do něj možnost výběru, zda je možno přidávat komentáře nebo ne.

Stejně dobře bych si mohl nadefinovat nějakou prázdnou funkci v předkovi všech modulů a pak jí jen podle potřeby přepsat, ale s rostoucím počet hooků by se celá třída stávala dosti velká a při větším množství modulů by se celkem zbytečně volala kopa funkcí, které nic nedělají. Obecně jsem se pak řídil pravidlem, že co bude pravděpodobně ovlivňovat každý modul (např. oprávnění, sitemapa, routy…), jsem realizoval pomocí prázdné funkce v předkovi, ale to, co bude využívat menší množství modulů, jsem vyřešil pomocí hooků.

před 9 lety

ruff
Člen | 11
+
0
-

Panda napsal(a):

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
{

Prosím tě, kde máš umístěnou tuto třídu?

před 9 lety

Panda
Člen | 570
+
0
-

app/application/SiteApplication.php, přepisuji i některé další třídy, které s aplikací souvisí, takže v té složce těch souborů mám víc.

před 9 lety

ViliamKopecky
Nette hipster | 231
+
0
-

@Panda: Nechceš to třeba sepsat formou článku, myslím, že tvoje řešení je dost dobré a dotažené, může velmi dobře posloužit k inspiraci. Myslím, že bych nebyl jediný, kdo by to ocenil.

před 9 lety

Panda
Člen | 570
+
0
-

enoice: Mno já si zrovna myslím, že do dotaženosti má mé řešení ještě daleko… Ale je fakt, že kdybych něco publikoval, tak by se to možná dalo společnými silami nějak dotáhnout. Něco tedy sepíšu, ale až časem. Možná bych se mohl zaměřit i na další věci, např. jednoduchá cesta k vlastním routám, ještě šikovnější Permission a tak.

před 9 lety

iguana007
Člen | 971
+
0
-

Taky bych se primluvil za nejaky clanek, ktery by tento postup vice vysvetlil …

před 9 lety

vyvazil.jakub
Člen | 6
+
0
-

Adresářová struktura je super, ale fakt dlouho jsem se propracovával ke všem informacím, které jsem potřeboval. Chápu, že dodělat dokumentaci je hodně práce, ale možná by nebylo na škodu udělat skeleton2 s rozdělením aplikace do modulů, aby tam byl {plink} mezi modulama.

Moje chyba, teď jsem si všiml, že to je v examples :)

Editoval vyvazil.jakub (3. 12. 2009 12:52)

před 8 lety

Vyki
Člen | 391
+
0
-

Stále je mi ten článek od Pandy velkou inspirací. A adresářovou strukturou jsem si nakonec poradil tak, že jsem vymyslel svojí:

.FirstModule
  ->frontend
      ->presenters
      ->tempates
  ->backend
       ->presenters
       ->tempates
  ->models
  ->modul.ini

.SecondModule
  ->frontend
      ->presenters
      ->tempates
  ->backend
       ->presenters
       ->tempates
  ->models
  ->modul.ini
.presenters - zde mím BasePresenter
.templates  - zde mám uložený globální layout
.components - zde mám obecné
config.ini

Aby toto šlo udělat tak jsem si vytvořil a jako službu service.Nette-Application-IPresenterLoader zaregistroval vlastní (podědil a upravil metodu formatPresenterFile) PresenterLoader, tak aby mi to akceptovalo novou adr. strukturu. Načítání layoutu a template jsem si ošetřil přepsáním metod presenteru formatLayoutTemplateFiles, formatTemplateFiles, které jsem uložil do BasePresenteru. V každém modulu podle toho schématu mám konfigurační soubor modul.ini, kde mám uvedeny, některé záležitosti (hooks, práva..) jako psal Panda. Ty konfigurační soubory načítám při startu aplikace. Myslíte, že se je vyplatí cachovat?

Editoval Vyki (18. 3. 2010 14:34)

před 8 lety

Honza Marek
Člen | 1674
+
0
-

Vyki napsal(a):

Aby toto šlo udělat tak jsem si vytvořil a jako službu service.Nette-Application-IPresenterLoader zaregistroval vlastní (podědil a upravil metodu formatPresenterFile) PresenterLoader, tak aby mi to akceptovalo novou adr. strukturu.

Vždyť to není potřeba. RobotLoader umí načíst presentery odkudkoliv. Úkolem IPresenterLoaderu je jen zjistit jméno třídy.

před 8 lety

westrem
Člen | 398
+
0
-

Sice je to uz nejaky ten mesiac co tu Panda pisal svoj prispevok o tom ako ma on zariesenu svoju aplikaciu ale chcel by som sa spytat – napisal potom k tomu aj nejaky ten clanok ako pise vo svojom prispevku? Ak ano, je niekde dostupny?

Pripadne vedel by ma niekto odkazat na nejake rozumne studijne materialy ohladne hooks a ako best practise s nimi spojene?

Vrela vdaka za akykolvek podnet!

před 8 lety

Filip Procházka
Moderator | 4693
+
0
-

články v dokumentaci wordpressu jsou imho docela k ničemu, protože tam se používá procedurální přístup a já osobně jsem to ani pořádně nepochopil :)

před 8 lety

knyttl
Člen | 197
+
0
-

Co se týče konfigurace adresářů v config.ini:

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

Já bych potřeboval ten adresář templatesDir být schopen měnit za běhu aplikace – je toto nějak možné? Přijde mi hloupé kvuli jednomu adresáři přepisovat celou funkci formatTemplateFiles()…

před 8 lety

kravčo
Člen | 723
+
0
-

Zatiaľ, kým máme vo frameworku Environment to pôjde takto:

Environment::setVariable('templatesDir', '/cesta/z/mesta');

Editoval kravčo (7. 10. 2010 0:07)

před 8 lety

knyttl
Člen | 197
+
0
-

Toto jsem samozřejmě zkoušel (zkusil jsem to tedy znovu a s nejnovější nightly verzí), proměnná na to ale nejmenší vliv. Zkoušel jsem v bootstrapu, v __construct u presenteru, beze změny.

před 8 lety

kravčo
Člen | 723
+
0
-

Aha, ty potrebuješ meniť adresár, z ktorého sa načítavajú templejty… Nette interne premenné ako templatesDir vôbec nepoužíva už vyše roka (od 6b45a1f), no neviem či je táto zmena aj v 0.9.x

Čiže naozaj ti asi nezostáva iné ako prepísať formatTemplateFiles().

před 8 lety

Ginny
Člen | 38
+
0
-

Musíme Pandu k nějakému článku vyhecovat :-)