Mirin webspace

Nejbohatší život má ten, kdo žije s minimem nároků

10. 6. 2009 - Komentáře (4) Zend Framework

Nahrávání tříd v Zend Frameworku 1.8

Jak psal na Intervalu nedávno Ronnie, jednou ze změn v Zend Frameworku v řadě 1.8 je autoloading. Ve zmíněném článku je popsáno o co jde a jak upravit svůj kód tak aby více méně fungoval i pod verzí 1.8. Pokusím se na toto téma podívat trochu z jiného pohledu.

Alespoň dva autolodery

První věc, kterou si je třeba uvědomit, je to, že v aplikaci se budete muset pravděpodobně zabývat minimálně dvěma typy autoloaderů, dříve byl ve frameworku v podstatě jen jeden autoloder na všechno.

První je klasický "globální" autoloader, který se stará o nahrávání tříd podle namespaces konvencí z include_path. Jeho API se také od verze 1.7 podstatně změnilo o tom více ve výše zmíněném článku.

Druhým typem autoloaderů jsou tzv. resources loadery, které slouží zejména k nahrávání tříd s různými aplikačně specifickými zdroji jako jsou formuláře, front controller pluginy, helpery atd. Jeho představitelem je zejména Zend_Application_Module_Autoloader, který zajišťuje nahrávání resources podle doporučených adresářových konvencí frameworku. Nic vám však nebrání použít jeho předka Zend_Loader_Autoloader_Resource pro vlastní uspořádání adresářů či si napsat úplně vlastní resource loader implementující resource loader interface.

Propojení loaderů

Jde o to, že musíme našemu "hlavnímu" loaderu říci, že pro naše resource chceme používat náš resource loader. Tato věc součástí Zend_Loader_Autoloader_Resource a vypadá takto

Zend_Loader_Autoloader::getInstance()->unshiftAutoloader($this, $namespace);

To znamená, že resource loader se přidá na začátek seznamu všech loaderů v našem hlavním globálním loaderu. Pokud tedy určitá třída v daném namespace nebude nahrána naším resource loaderem, tak se o její nahrání pokusí hlavní autoloader přes include_path.

Zend_Application a zpětná kompatibilita s non namespace modely

Takže už víme to hlavní o rozdílech v loaderech ve frameworku verze 1.8. Na první pohled je vidět, že framework nově velmi tlačí na používání namespaces a to i v resources (modely, formuláře). To nám může trochu nabourat náš původní kód, zejména modely. Spousta lidí nepoužívala namespaceované business třídy modelů. Většinou jste měli třídy jako User, Product, Ticket nikoli MyApp_User, MyApp_Product, MyApp_Ticket. Většinou jste je také měli umístěné někde v adresáři models, ten jste měli v include_path a nahrávali je přes klasický globální autoloader. Toto můžete použít i dnes, jen musíte povolit toto chování v globálním autoloaderu takto:

$appAutoloader->setFallbackAutoloader(true);

Nebudu se více rozepisovat o podrobnostech novinky Zend_Application, co se týká autoloaderů jde o to je nějak inicializovat podle nových pravidel Zend_Application a použít výše zmíněné nastavení pro zpětnou kompatibilitu pojmenování modelů. Toho docílíme níže popsanou metodou třídy našeho aplikačního bootstrapu. Je tam ještě jedna věc, o které jsem se nezmínil, nastavení výpisu chyb globálního autoloderu při nezdařeném nahrání třídy pokud jsme v módu jiném než produkčním - metoda suppressNotFoundWarnings. Obě věci - setfallbackAutoloader() a suppressNotFoundWarnings() je dobré si pohlídat, protože implicitní nastavení je takové, že se fallbackAutoloader nepoužije - původně pojmenované modely se nebudou nahrávat a notFoundWarnings se nevypisují.

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
    /**
     * Bootstrap autoloader for application resources.
     * It also makes settings in an application autoloader.
     * @return Zend_Application_Module_Autoloader
     */
    protected function _initAutoload()
    {
        /** application autoloader
         * @var Zend_Loader_Autoloader
         */
        $appAutoloader = $this->getApplication()->getAutoloader();
        //enable classic include path directory loader
        $appAutoloader->setFallbackAutoloader(true);
        //enable warnings for autoloading errors
        $appAutoloader->suppressNotFoundWarnings($this->getApplication()->getEnvironment() == "production");
 
        //resource autoloader
        $autoloader = new Zend_Application_Module_Autoloader(array(
            'namespace' => 'HomeWebApp',
            'basePath'  => dirname(__FILE__),
        ));
 
        return $autoloader;
    }

To nic nemění na tom, že časem by bylo vhodné názvy tříd modelů dát pod namespace a použít na ně resource loader, nejlépe Zend_Loader_Autoloader_Resource a přidržet se konvencí frameworku pro pojmenování adresářů, ty jsou zde.


Komentáře (4)

  1. anonym - 10. 7. 2009 13:01

    vím že to sem nepatří, ale nevidím nikde kontakt na tebe:
    RSS článků obsahuje komentáře, tak to pls oprav
    a tohle smaž :-)

  2. snop - 10. 7. 2009 15:30

    jj, vcera to jeste bylo ok, ale dnes rano jsem dostal z tveho RSS i komentare k clankum

    Je to nejaka feature-a, kdyz jo tak pls oddel kometare k clankom a od clanku

    Pro kazde by mnel by zvlast RSS kanal

    Dekuji za rychli fix, nez se mi tve RSS zabordeluji komentarema

  3. koubel - 10. 7. 2009 18:55

    [1][2][3] - Ano, přehodil jsem to na novou verzi (je v repositáři) už na Zend Frameworku 1.8.x, kterou jsem zhusta upravoval, takže tam jsou chyby, které jsem nevychytal, omlouvám se, to se holt stává.

    To rss by mělo být opraveno.

Komentáře jsou uzavřeny.