Zend Framework daje nam dużą swobodÄ™ konfiguracji struktury katalogów. IstniejÄ… już w obecnej wersji frameworka narzÄ™dzia, przyspieszajÄ…ce proces tworzenie szkieletu, takie jak Zend_Console oraz Zend_Build, jednak jeszcze w tym momencie mnie nie przekonujÄ… (znacznie ciekawsze narzÄ™dzia udostÄ™pnia Symfony). Elastyczna struktura to podstawa, a sklejanie wszystkich elementów przy każdym nowym projekcie jest po prostu stratÄ… czasu. Dlatego warto mieć wczeÅ›niej przygotowanego “gotowca”.
W tym przykładzie wykorzystam najbardziej (moim zdaniem) uniwersalną modułową strukturę projektu. Uzyskamy dzięki temu możliwość separacji poszczególnych modułów aplikacji.
Przykład takiej strutury katalogów:
index.php
application/
modules/
default/
controllers/
IndexController.php
models/
views/
index/
admin/
controllers/
IndexController.php
models/
views/
index/
library/
Zend/
public/
images/
js/
css/
Gdzie moduł admin możemy uznać jako szkielet panelu, do którego będziemy mogli podpiąć niezależne moduły. Podobnie w przypadku widoku użytkownika - tam podobną rolę będzie spełniał module default.
Aby mieć możliwość łatwego wywoływania klas bibliotek Zenda czy też naszych modeli musimy wskazać katalogi w których PHP ma szukać tychże klas. Kod dodajemy do pliku index.php:
<?php
set_include_path(
'.' . PATH_SEPARATOR .
'./library/' . PATH_SEPARATOR .
'./application/modules/' . PATH_SEPARATOR .
get_include_path()
);
?>
Trzymając się tej konwencji, nazwy kontrolerów muszą zostać poprzedzone prefixem - nazwą modułu - np. admin_IndexController. Nie dotyczy to jednak controlerów znajdujących się w katalogu defaultowym, wystarczy: IndexController.
Do prawidłowego działania aplikacji należy dodatkowo zdefiniować miejsce controllerów w strukturze dla poszczególnych modułów (plik index.php):
<?php
/* Utworzenie obiektu kontrolera */
$front = Zend_Controller_Front::getInstance();
/* Ustawienie ścieżki dla modołów */
$front->addModuleDirectory('application/modules');
?>
Domślny rounting Zenda oczekuję jednego z poniższych schamtów:
:module/:controller/:action/*
:controller/:action/*
Dla definiowania ścieżek routingu można wykorzystać np. wpisy w pliku konfiguracyjnym. Przykładowy trasy routingu dla pliku config.ini:
[routes] ;trasa routingu domyślnego default.route = ":controller/:action/*" default.defaults.module = "default" default.defaults.controller = "index" default.defaults.action = "index" ;Trasa routingu dla admina admin.route = "admin/:controller/:action/*" admin.defaults.access = "admin" admin.defaults.module = "admin" admin.defaults.controller = "index" admin.defaults.action = "index"
Teraz wystarczy przekazać tą konfigurację do front kontrolera (index.php):
<?php
/* Pobranie konfiguracji */
$config = new Zend_Config_Ini('application/config.ini', null);
/* Domślny router */
$router = $front->getRouter();
/* Ustawienie konfiguracji routera */
$router->addConfig($config,'routes');
?>
Pozostaje jeszcze ustawić ścieżki dla katalogów z modelami w poszczególnych modułach - niezbędne do korzystania z domyślnego silnika bazodanowego Zenda (w jednym z następnych tutoriali zastąpię go Doctrine). Można to zrobić na kilka sposobów. Możemy dodać ścieżki dla każdego modułu osobno, ustawić je w funkcji init() controllera nadrzędnego (tak zrobimy w przypadku implementacji Smartów) lub też w Pluginie - co kto lubi:) Ja wykorzystam do tego Plugin (ModelDirectory.php w katalogu application/assistant/Plugin):
<?php
require_once 'Zend/Controller/Plugin/Abstract.php';
class Plugin_ModelDirectory extends Zend_Controller_Plugin_Abstract
{
public function dispatchLoopStartup(Zend_Controller_Request_Abstract $req)
{
$module = $req->getModuleName();
set_include_path(
get_include_path() . PATH_SEPARATOR .
"./application/modules/$module/models/"
);
}
}
?>
Należy jeszcze dodać do naszej struktury katalog, w którym bÄ™dziemy przechowywali pluginy aplikacji. W tym przypadku tworzymy katalog “assistant” (nazwa katalog jest dowolna - najlepiej intuicyjna) w katalogu “application”, a w nim katalog “Plugin”, do którego dodajemy naszÄ… klasÄ™: ModelDirectory.php. Należy też pamiÄ™tać by dodać folder “assistant” do “set_include_path” by Å‚atwiej wywoÅ‚ywać klasy:
<?php
set_include_path(
'.' . PATH_SEPARATOR .
'./library/' . PATH_SEPARATOR .
'./application/modules/' . PATH_SEPARATOR .
'./application/assistant/' . PATH_SEPARATOR .
get_include_path()
);
?>
Teraz w index.php rejestrujemy plugin:
<?php
$front->registerPlugin(new Plugin_ModelDirectory());
?>
Czy mógłbyś dokładnie opisać, w których plikach należy wstawić pokazany kod i czy jest to kompatybilne z ZF 1.8?
Oczywiście mógłbym, postaram się to zrobić wieczorem. Co do kompatybilności z 1.8 - uważam, że nie powinno być z tym problemu. Jednak sprawdzę to dokładniej bo ostatnio niestety nie jestem na bieżąco z Zendem.
ChciaÅ‚bym poprzeć proÅ›bÄ™ PE co do tych plików. ZrobiÅ‚em dokÅ‚adnie wg tego co opisaÅ‚eÅ›, dobrze mi dziaÅ‚ajÄ… foldery controllers i views, ale oprócz nich mam jeszcze layout, którego nie udaje mi siÄ™ podpiąć. Od piÄ…tku kombinuje z tym, ale coÅ› nie idzie… dziÄ™ki za pomoc
-tutorial bardzo dobrze napisany!
Napisz w którym momencie masz problem to chętnie pomogę, a przy okazji zaktualizuję wpisy.
zrobiłem wszystko wg opisu, choć lepiej by się pracowało jakby każdy kod był opisany z jakiego pliku pochodzi. Moduły mi działają, tylko jeszcze bym chciał by każdy miał własny layout, więc z każdym module oprócz /controllers i /view mam jeszcze /layouts (/scripts/layout.phtml), ale niestety mam problem jak to podłączyć.
ZnalazÅ‚em inny tutorial (bez modułów) i tam jest ustawiany layout poprzez wpisy do Zend_Application: “resources.layout.layout = “layout” resources.layout.layoutPath = APPLICATION_PATH “/layouts/scripts”. Niestety niewiem jak to zrobić dla modułów.
Wszystko pięknie, tylko do tej pory w tutorialu nie było nic na temat layoutu. Jak podpiąć layout dla każdego modułu jest w następnym tutorialu, a konkretnie kod:
/* konfiguracja Layoutu */
$options = array(
‘viewSuffix’ => ‘tpl’,
‘layoutPath’ => getcwd() . ‘/application/modules/’ . $this->_request->getModuleName() . ‘/views/’,
);
który należy umieścić w pliku Core_Controller_Action.php - przy założeniu, że korzystasz z Zend_Layout.
Wszystko pieknie, ładnie, ale co rusz wydaje mi się jakby tekst ucięło.
Np. W którym miejscu jest odpalana metoda dispatchLoopStartup() ??
Tak dla ścisłości, to dokumentacja Zenda sugeruje żeby nie dopisywać ?> w plikach php, które zawierają jedynie kod. Jeżeli za takim znacznikiem przypadkowo dodasz znak nowej linii, to wczytanie tego pliku spowoduje wysłanie tego znaku do bufora wyjściowego i zablokuje wysyłanie nagłówków php.
Powinieneś dodać odnośnik do http://framework.zend.com/manual/en/zend.application.html, bo prawdopodobnie tym się sugerowałeś pisząc ten artykuł (nie wiem czemu nie Dodałeś ErrorController) i wiele osób mogłoby porównać Twoją interpretację z sugestiami i dokumentacją autorów.
Pozdrawiam,
Macvek
Tak dla ścisłości:
1. Każdy fragment kodu PHP jaki prezentuję, umieszczam między znacznikami rozpoczynającymi i kończącymi (odpowiednio < ?php i ?>). Bez względu na to czy jest fragment kodu zawierający wywołanie klasy/metody czy też cała klasa - zdaje sobie sprawę, że dla niektórych może być to mylące i całkowicie się zgadzam, że powinno się ich zamykać;
2. Co do linku do mauala (zend.application) - pisząc ten artykuł owy tutorial jeszcze nie istniał, także trudno byłoby mi się czymkolwiek sugerować. Na stronie Zenda można było wtedy przeczytać jedynie stary Quick Start z którego za wiele nie wynikało - ostatnio się trochę poprawili (czyt. zaktualizowali tutorial), jednakże do tutoriali na stronie Symfony im daleko.
Pozdrawiam,
Kamil