Přeskočit na hlavní obsah

Zend framework - jak vytvořit modul

Úvod

V příspěvku se zmíním o způsobu, jak vytvořit modul v Zend Frameworku. Dále si povíme o jeho registraci v projektu a namapování zdrojů, které bude daný modul používat.

Jednu poznámku hned na začátku, seznam proměnných, které budu používat v textu:

  • %APACHE_HOME% - adresář, v kterém máte nainstalován httpd server
  • %APP_HOME% znamená %APACHE_HOME%/htdocs/zendapp/application, jedná se o lokaci aplikace, na které budu vysvětlovat tento návod

Architektura projektu

Adresářová struktura ZF projektu hraje klíčovou roli. Základní stavební jednotkou projektu je modul. Základní struktura aplikace, kterou získáváte stažením Zend Frameworku je považována za defaultní modul. Nicméně při implementaci větších projektů se setkáte s tím, že projekt je potřeba rozdělit na několik logických celků (administrace, blog, fotogalerie atd.). ZF nabízí architektům moduly.

Je žádoucí ZF projekt rozdělit na moduly a rozvrhnout i adresářovou strukturu (tzv. resource type) samotného modulu (defaultní struktura modulu dle ZF). V defaultním modulu jsou již některé podadresáře (resource type) zaregistrovány:

code 0.
/**
     * Initialize default resource types for module resource classes
     *
     * @return void
     */
    public function initDefaultResourceTypes()
    {
        $basePath = $this->getBasePath();
        $this->addResourceTypes(array(
            'dbtable' => array(
                'namespace' => 'Model_DbTable',
                'path'      => 'models/DbTable',
            ),
            'mappers' => array(
                'namespace' => 'Model_Mapper',
                'path'      => 'models/mappers',
            ),
            'form'    => array(
                'namespace' => 'Form',
                'path'      => 'forms',
            ),
            'model'   => array(
                'namespace' => 'Model',
                'path'      => 'models',
            ),
            'plugin'  => array(
                'namespace' => 'Plugin',
                'path'      => 'plugins',
            ),
            'service' => array(
                'namespace' => 'Service',
                'path'      => 'services',
            ),
            'viewhelper' => array(
                'namespace' => 'View_Helper',
                'path'      => 'views/helpers',
            ),
            'viewfilter' => array(
                'namespace' => 'View_Filter',
                'path'      => 'views/filters',
            ),
        ));
        $this->setDefaultResourceType('model');
    }

Jak vytvořit modul

Nejdříve vytvořme adresář modules v %APP_HOME. Lze ho vytvořit ručně, anebo použijeme utilitu zf a zavoláme následující příkaz:

code 1.
zf create module admin

V adresáři modules bude nyní podadresář admin a v něm podadresáře controllers, models, views. Jak vidíte modul „by měl“ (názvy lze však změnit a to buď v konfiguraci – application.ini, anebo v Bootstrap.php) obsahovat alespoň výše uvedené adresáře. Návrh ZF projektu je postaven na návrhovém vzoru MVC [nebo], což vysvětluje pojmenování adresářů.

Dále musíme zaregistrovat v soubor %APP_HOME%/configs/application.ini v sekci [production] zaregistrovat modules adresář.

code 2.
resources.modules = ""
resources.frontController.moduleDirectory = APPLICATION_PATH "/modules"

Dále musíme v adresáři příslušného modulu vytvořit soubor Bootstrap.php a v něm vytvořit třídu, která bude mít v signatuře název %modulenamespace%_Bootstrap, která dědí od Zend_Application_Module_Bootstrap. V našem případě, se jedná o administrační modul aplikace, který se nachází v %APP_HOME%/modules/admin a kód bude vypadat následovně:

code 3.
class Admin_Bootstrap extends Zend_Application_Module_Bootstrap {
  // Admin_ je namespace, kterym musi byt uvozena tato trida, 
  //aby ji autoloader nasel.
}

Ještě jednou upozorňuji, že aplikace, kterou jsme si nechali vygenerovat za pomocí zf create project zendapp je chápán jako defaultní modul. Modul a jeho adresářovou strukturu musí namapovat „autoloader“, jak jsem provedli v ukázce kódu code 3. a toto namapování se inicializuje v průběhu tzv. boostrap procesu. Konkrétní registrace se provádí metodou _initAutload:

code 4.
class Admin_Bootstrap extends Zend_Application_Module_Bootstrap {
    protected function _initAutoload() {
        $moduleLoader=new Zend_Loader_Autoloader_Resource(array(
            'basePath' => APPLICATION_PATH . "/modules/admin",
            'namespace' => 'Admin',
       ));
    }

}

V tuto chvíli máme vygenerovaný skelet modulu admin a připravený bootstraper, abychom ho mohli dále konfigurovat v rámci projektu.

Namapování adresářové struktury modulu

Bez namapovaného autoloaderu a registrovaného namespace nebudou vaše třídy dohledatelné (do jisté míry lze zajistit automatické dohledání tříd, ale tzv. fallback autoloader není doporučován!)- viz citace níže, která je převzatá z oficiální dokumentace Zend framework.

Provide namespace matching. If the class namespace prefix is not in a list of registered namespaces, return FALSE immediately. This allows for more optimistic matching, as well as fallback to other autoloaders.

Struktura adresáře modulu obsahuje další podadresáře (models, service, controller atd.). Tyto adresáře ZF je také nutné namapovat. ZF je nazývá jako resource-type. V kapitole Architektura projektu je výpis adresářů, které jsou namapovány v defaultním modulu. Přesně tímto způsobem lze přidávat/editovat adresáře v rámci dalších modulů. Namapování adresářů zajistíme pomocí metody addResourceType:

code 5.
class Admin_Bootstrap extends Zend_Application_Module_Bootstrap {
    protected function _initAutoload() {
        $moduleLoader=new Zend_Loader_Autoloader_Resource(array(
            'basePath' => APPLICATION_PATH . "/modules/admin",
            'namespace' => 'Admin',
       ));
      $moduleLoader->addResourceType('testdir', 'testdir', 'Testdir');
    }
}

První parametr je typ zdroje (jednoznačný identifikátor zdroje – používá ZF), druhý definuje název adresáře v rámci modulu a třetí je prefixem, který se zapisuje do názvu tříd. Nyní jsem schopni kdekoli v rámci projektu instancovat své implementace, protože inicializovaný autoloader modulu v závislosti se zaregistrovaným namespace modulu je schopen třídu nalézt. Samozřejmě i implementace v jiných modulech - o to se již postarají autoloadery jednotlivých modulů.

Maska pro název a samotné instancování třídy je stejná : %modulenamespace%_%resourcetype%_%filename%. V tuto chvíli předběhnu a řekněme, že budeme adresovat objekt Person ve svém controller action, který bude např. řešit CRUD akce.

code 6.
class IndexController extends Zend_Controller_Action {
    public function createAction() {
        $test = new Zendapp_Testdir_Person();
    }
}
class Admin_IndexController extends Zend_Controller_Action {
    public function createAction() {
        $test = new Admin_Model_Enumeration();
    }
}

Shrnutí

Uff, dlouhý to článek – zaslouží si menší shrnutí, aby to bylo vstřebatelné. ZF nabízí modulární přístup, jak navrhnout strukturu projektu. Aplikace je defaultním modulem, která může obsahovat v libovolném adresáři (doporučeno modules) další „moduly“. Modulem chápeme samostatný logický celek aplikace (např. mzdy, personalistika).

Modul musí deklarovat „svůj“ autoloader, který poté pracuje s namespace modulu, který je nutné zaregistrovat a deklarovat jeho prefix. Namespace modulu se dále skládá z adresářové struktury, kterou je nutné namapovat a tím docílím, že autoloader dohledá naše třídy. ZF nabízí velmi (a to doslova) obecné řešení, které dovoluje architektům/vývojářům si namyslet jakoukoli strukturu aplikace.

Závěr

V tuto chvíli jste schopni navrhnout a vygenerovat strukturu projektu. Když půjdeme o trochu dále je možné vytvořit dávku, která bude generovat celý skelet projektu včetně modulů. Tím, že máte k dispozici utilitu, která používá příkazovou řádku vám nic nestojí v cestě (linuxáři nevrťte hlavou, v *unixu je to téměr standard přístup).

ZF a jeho návrh rozdělení aplikace do modulů zcela pokrývá možnost si nejenom aplikaci rozdělit do jednotlivých logických celků (mzdy, personalistika atd.), ale je možné si samotný modul (jeho namespace) „rozvstvit“ – ZF např. nabízí adresář services pro implementaci servisní vrstvy.

Případné potíže

  • v konsoli se objevuje hláška Cannot redeclare class Zend_Loader, tak si přečtěte tento příspěvek

Zdroje

Komentáře

Populární příspěvky z tohoto blogu

Letmý pohled na php frameworky Zend, CakePHP a Prado

Tento článek vyšel původně na blogu derhaa.com, který jsem však zrušil. Abstrakt Tento článek je předvojem seriálu o Zend Framework (u) – dále je tu velmi stručný rozbor,  jak sem nahlédl pod pokličku dalších dvou frameworků –  CakePHP (CP) a Prado (PD).  Mimochodem se zde stručně dozvíme jak frameworky pracují a soupis funkčností, kterými se od sebe odlišují. Cílem článku je povrchně seznámit čtenáře se třemi PHP frameworky, které se staly předmětem mého zájmu – v čem napsat středně veliký projekt.   Idea Když jsem přemýšlel v čem napíšu svůj první větší počin, tj. aplikace typu HRMS , jehož dalším cílem bude nad shromážděnými daty provádět specifické analýzy/statistiky související se sportovní tématikou. Předpokládal jsem, že to nebude malý projekt, který lze napsat na koleni, ale budu potřebovat sofistikovanější nástroje pro práci s databází ( ORM ),  propracovanější návrh doménového modelu , následné rozdělení aplikace na logické celky – vrstvy ...

Zend_Tool - Cannot redeclare class Zend_Loader

V mém případě, když jsem zadal následující příkaz: zf create module admin V konsoli se objevila následujicí hláška Cannot redeclare class Zend_Loader in path/to/library/Zend/Loader on line 31 Řešení je jednochuché - Nakopírujte soubory zf.bat a zf.php z adresáře %ZEND_FRAMEWORK_DIR%/bin do adresáře %PHP_HOME% . V případě, že chcete vědět více – mkrněte na oficiální dokumentaci Zend_Tool .

PHP a Zend Framework autoloading

Úvod V příspěvku se zmíním o způsobu a správě „importů“ (tzv. autoloading) php souborů v samotném PHP a poté se dozvíme, jak autoloading php souborů řeší Zend Framework. Autoloading v PHP Správa importů v PHP Jak "importovat" v PHP soubory Jak funguje mechanismus importů v PHP Autoloading v Zend Framework Autoloading v PHP Základem při psaní aplikací v PHP je nutné si uvědomit, jak funguje tzv. autoloading php souborů. V PHP neexistují importy jako je známe např. z Java. Když například potřebujete konstruhovat třídu jejíž definice je v jiném souboru – je nutné si tento soubor za pomocí konstrukce require nebo require_once ( include , include_once ) “naimportovat“ do svého souboru (předpokladem, je že soubory jsou umístěné na include_path ). Dalším řešením je překrýt funkci autoload . Správa importů v PHP Správa “importů” souborů v php mi přijde neštastná. Jedná se do jisté míry o problém, alespoň pro mne – jsem vývojářem v Java , kde tento mechanismus je zajišt...