Nastal čas Vianoc, obdobie, keď sme odbremenení od pracovných záležitostí a máme more času venovať sa vlastým záujmom. Ak ste hľadali schodný a jednoduchý spôsob ako preniknúť do tajov Zend Frameworku, hľadať už nemusíte. Ako vianočný darček Vám prinášam tento krátky seriál s tutoriálom v Slovenčine.
Text vznikol s láskavým dovolením pána Roba Allena. Jeho originálnu anglickú verziu môžete nájsť na jeho stránkach.
<prelozeny-text>
Tento tutoriál si kladie za cieľ, byť veľmi základným vstupným bodom pri používaní Zend Framework k písaniu webových a databázových aplikácií v PHP.
Pozn. Tento tutoriál bol testovaný so Zend Frameworkom verzie 1.0.0 Je vysoká pravdepodobnosť, že bude pracovať správne aj ďalšími verziami, napriek tomu je prednostne určený pre túto verziu.
Pozn. prekladateľa: Tutoriál som kompletne otestoval a funguje aj s najnovšou aktuálnou verziou Zend Framework 1.0.3.
Architektúra MVC (model, view, controller)
Tradičný spôsob písania PHP aplikácií vypadá ako napr. tento kód:
<?php
include "common-libs.php";
include "config.php";
mysql_connect($hostname, $username, $password);
mysql_select_db($database);
?>
<?php include "header.php"; ?>
<h1>Home Page</h1>
<?php
$sql = "SELECT * FROM news";
$result = mysql_query($sql);
?>
<table>
<?php
while ($row = mysql_fetch_assoc($result)) {
?>
<tr>
<td><?php echo $row['date_created']; ?></td>
<td><?php echo $row['title']; ?></td>
</tr>
<?php
}
?>
</table>
<?php include "footer.php"; ?>
Počas života aplikácie tohto typu, sa kód stáva čoraz viac ťažšie udržiavateľný , tak ako od klienta prichádzajú ďalšie a ďalšie požiadavky, ktoré musíme zložito hekovať na rôznych miestach do pôvodného kódu.
Jednou z metód ako zlepšiť spravovateľnosť aplikácie je rozdeliť kód do troch separátnych sekcií (a zvyčajne aj separátnych súborov):
- Model
- Model je časť aplikácie, ktorá má čo dočinenia s údajmi, ktoré chceme zobrazovať/ukladať. V predchádzajúcom príklade sa jedná o údaje z tabuľky
news
. Model sa týka tzv. biznis časti logiky našej aplikácie a stará sa teda o funkcie LOAD/STORE nad databázou - View
- View je časť aplikácie, ktorá ma starosti zobrazenie údajov užívateľovi. Tie sú najčastejšie prezentované vo forme HTML
- Controller
- Controller má na starosti prácu s modelom a view-om, tak aby pri špecifickom požiadavku dostal užívateľ správne údaje v správnej forme.
Zend Framework využíva architektúru MVC. Využíva ju k tomu aby oddelil rozličné časti aplikácie, tak aby boli vývoj a údržba jednoduchšie.
Požiadavky
Zend Framework má nasledovné požiadavky:
- PHP verzie 5.1.4 (alebo vyššia)
- WEB server so zapnutou funkciou
mod_rewrite
Predpoklady tutoriálu
Predpokladám, že používate PHP verzie 5.1.4 alebo vyššie, spolu s webovým serverom Apache. Vaša inštalácia Apache web servera musí mať povolené a nakonfigurované rozšírenie mod_rewrite
. Musíte tiež overiť, že Apache podporuje súbory .htaccess
Toto sa väčšinou dosiahne nasledujúcou konfiguračnou direktívou v konfigurácii servera:
AllowOverride None
prepíšte za
AllowOverride All
Preštuduje si dokumentáciu vašej distribúcie pre zmenu tejto konfigurácie. Pamätejte, že nebudete schopný zobraziť inú ako titulnú stránku bez podpory mod_rewrite
a .htaccess
.
Získanie Frameworku
Zend Framework je možné získať zo stránky http://framework.zend.com/download vo formáte .zip
alebo .tar.gz
.
Adresárová štruktúra
Zend Framework neprikazuje presnú adresárovú štruktúru, ale manuál odporúča využívať všeobecne doporučenú štruktúru. Táto štruktúra predpokladá, že máte plnú kontrolu nad konfiguráciou web servera, napriek tomu si život trocha zpriemnime a toto odporučenie mierne modifikujeme.
Začnite vytvorením adresára zf-tutoriál
vo vašom web_root
adresári. To znamená, že URL na tento adresár bude mať tvar http://localhost/zf-tutorial
.
Ďalej vytvorte nasledovnú štruktúru podadresárov:
zf-tutorial/
/application
/controllers
/models
/views
/filters
/helpers
/scripts
/library
/public
/images
/scripts
/styles
Ako vidíte, v aplikácii máme samostatné adresáre pre súbory model, view a controller. Obrázky, javascript a CSS súbory sú uložené vo vlastných adresároch podadresára
public
. Knižnice stiahnutého Zend Frameworku sú uložené v adresári library
. Ak budete potrebovať vytvárať vlastné knižnice a triedy, umiestnite ich tiež do tohto adresára. Stiahnutý archív rozbaľte do dočasného adresára. Všetky súbory sú umiestnené v podadresári v mojom prípade ZendFramework-1.0.0
. Skopírujte adresár library/Zend
do vašej aplikácie, do adresára library
. Váš adresár zf-tutorial/library
by tak mal obsahovať nový adresár nazvaný Zend
.
Bootstrap
Controller Zend Frameworku, Zend_Controller
je navrhnutý na pre podporu internetových stránok s peknými URL. Aby sme toto dosiahli, musíme všetky požiadavky (requesty) vybavovať cez jediný súbor index.php
, nazývaný tiež bootstrapper. Toto nám poskytne centrálny bod pre všetky stránky a zaručí, že prostredie bude pre aplikáciu správne nakonfigurované. Takéto správanie dosiahneme použitím súboru .htaccess
v adresári web_root
.
zf-tutorial/.htaccess
RewriteEngine on
RewriteRule .* index.php
php_flag magic_quotes_gpc off
php_flag register_globals off
Prepisovacie pravidlo je veľmi jednoduché môžeme ho interpretovať takto: „pre ľubovoľnú URL použi index.php“.
Zmenili sme tiež niekoľko direktív z php.ini
. Mali by byť už správne nastavené v php.ini
ale chceme mať istotu. Je treba pamätať na to, že prepisovanie konfiguračných direktív PHP v súbore .htaccess
je funkčné iba ak PHP beží ako modul Apache servera. Ak PHP beží ako CGI/FastCGI, overte tieto nastavenia v php.ini
.
Napriek tomuto nastaveniu je vhodné aby javascript, CSS a obrázkové súbory neboli presmerované bootstraperom. Tým, že sme tieto súbory umiestnili do samostatného adresára public
, môžeme Apache server jednoducho nakonfigurovať aby tieto súbory poskytoval priamo. Použijeme k tomu ďalší súbor .htaccess
v adresári zf-tutorial/public
:
zf-tutorial/public/.htaccess
RewriteEngine off
Ďalšie nastavenie nie je striktne potrebné, ale pre lepšiu ochranu našej aplikácie vytvoríme ešte niekoľko súborov s rewrite pravidlami:
zf-tutorial/application/.htaccess
Deny From All
zf-tutorial/library/.htaccess
Deny From All
Pamätajte, že pre využívanie súborov .htaccess
je potrebné aby mal Apache vo svojom hlavnom konfiguračnom súbore httpd.conf
nastavenú direktívu AllowOverride
na hodnotu All
. Táto myšlienka s využívaním mnohých súborov .htaccess
je podrobne popísaná v článku Jaysona Minarda, Blueprint for PHP Applications: Bootstrapping (Part 2). Odporúčam vám aby ste si prečítali obe časti.
Bootstrap súbor: index.php
Súbor zf-tutorial/index.php
je naším bootstrapovým súborom. Naplňte ho nasledujúcim kódom:
zf-tutorial/index.php
<?php
error_reporting(E_ALL|E_STRICT);
date_default_timezone_set('Europe/Bratislava');
set_include_path('.' . PATH_SEPARATOR . './library'
. PATH_SEPARATOR . './application/models/'
. PATH_SEPARATOR . get_include_path());
include "Zend/Loader.php";
Zend_Loader::loadClass('Zend_Controller_Front');
// setup controller
$frontController = Zend_Controller_Front::getInstance();
$frontController->throwExceptions(true);
$frontController->setControllerDirectory('./application/controllers');
// run!
$frontController->dispatch();
Všimnite si, že sme nepoužili ukončovacie ?>, nakoľko to nie je potrebné a ponechanie otvoreného konca nás ochráni pred rôznymi ťažko laditeľnými chybami, ktoré sa objavia pri presmerovaní cez funkciu header()
ak ponecháme na konci súboru nejaké biele znaky.
Popíšme si obsah súboru:
error_reporting(E_ALL|E_STRICT);
date_default_timezone_set('Europe/Bratislava');
Tieto riadky zaručia, že uvidíme akúkoľvek chybu, ktorú urobíme (predpokladom je nastavená direktíva display_errors v php.ini
na hodnotu on
). Okrem toho nastavíme miestnu časovú zónu, nakoľko je to požiadavka PHP 5.1 a vyšších. Môžete samozrejme nastaviť vlastnú časovú zónu.
set_include_path('.' . PATH_SEPARATOR . './library'
. PATH_SEPARATOR . './application/models/'
. PATH_SEPARATOR . get_include_path());
include "Zend/Loader.php";
Zend Framework je navrhnutý tak, že súbory sa nachádzajú v tzv. include ceste. Do tejto cesty sme tiež pridali náš model adresár, takže môžeme jednoducho nahrávať naše triedy z model adresára. Pokračujeme inkludovaním súboru Zend/Loader.php
, čo nám dáva prístup ku triede Zend_Loader
, ktorá poskytuje potrebné statické funkcie pre nahrávanie ostatných tried Zend Frameworku.
Zend_Loader::loadClass('Zend_Controller_Front');
Tento príkaz načíta vymenovanú triedu. To je dosiahnuté skonvertovaním podtržítok v názve triedy na oddeľovače cesty a pridaním koncovky .php. To znamená, že trieda Zend_Controller_Front
sa inkluduje zo súboru Zend/Controller/Front.php
. Ak dodržíte rovnakú mennú konvenciu, môžete takto načítavať vlastné triedy využitím s Zend_Loader::loadClass()
Prvou triedou, ktorú budeme potrebovať je front controller.
Front controller používa routovaciu triedu na mapovanie požadovaného URL na PHP funkciu, ktorá bude použitá na zobrazenie stránky. Pre správnu funkciu routra mu potrebujeme povedať, ktorá časť URL smeruje na index.php, takže sa môže na URL elementy pozerať za týmto bodom. Toto zabezpečuje tzv. Request objekt. Ten odvádza veľmi dobrú prácu pri auto detekcii základu URL, ale ak zlyhá, môžete ho manuálne nastaviť pomocou funkcie $frontController->setBaseUrl()
.
Front controller potrebujeme nastaviť aby vedel, kde má hľadať ďalšie controllery.
// setup controller
$frontController = Zend_Controller_Front::getInstance();
$frontController->throwExceptions(true);
$frontController->setControllerDirectory('./application/controllers');
Nakoľko naša aplikácia beží v testovacom móde, rozhodol som sa nastaviť front controller tak aby vyhadzoval všetky výnimky, ktoré sa objavia. Defaultne tak front controller bude pre nás odchytávať výnimky a ukladať ich do člena _exceptions
objektu Response, ktorý vytvorí. Objekt Response drží všetky informácie o odpovedi na požadovanú URL. To zahŕňa http hlavičky, obsah stránky a výnimky. Front controller pošle hlavičky a obsah stránky až nakoniec, takže sa všetky výnimky zobrazia hneď na vrchu stránky. Ale na produkčnom serveri by užívateľ nemal nikdy žiadnu výnimku vidieť!
Nakoniec sa dostávame k tomu hlavnému – aplikáciu spustíme:
// run!
$frontController->dispatch();
Ak si v browseri zobrazíte adresu http://localhost/zf-tutorial/
dostanete chybovú hlášku podobnú tejto:
Fatal error: Uncaught exception 'Zend_Controller_Dispatcher_Exception' with
message 'Invalid controller specified (index)' in…
Tá nám vraví, že sme aplikáciu ešte nenastavili. Predtým ako tak spravíme, popíšem aplikáciu, ktorú ideme napísať a aké bude mať funkcie.
Stránka
Ideme si napísať veľmi jednoduchú aplikáciu, inventárny systém pre našu kolekciu CD. Hlavná stránka nám vylistuje kolekciu a umožní pridať, editovať a zmazať záznamy kolekcie. Kolekcia je uložená v databáze v takejto tabuľke:
Meno stĺpca Dátový typ Null? Misc
-------------------------------------------------------------------
Id Int No Primary key, autoincrement
Artist Varchar(100) No
Title Varchar(100) No
Jednotlivé stránky
Budeme potrebovať tieto stránky:
- Home page
- Zobrazí listovanie kolekcie, poskytuje linky na editáciu a zmazanie albumu. A okrem toho zobrazuje aj link na pridanie nového albumu.
- Add new album
- Táto stránka zobrazí formulár na pridanie albumu
- Edit album
- Táto stránka zobrazí formulár na editovanie albumu
- Delete album
- Táto stránka zobrazí potvrdenie, či chceme zmazať album
Organizácia stránok
Predtým ako si napíšeme kód jednotlivých súborov, popíšeme si ako Framework očakáva, že budú stránky organizované. Každá stránka v aplikácii je istou akciou a akcie sú zoskupené v controlleroch. Napr. pri URL http://localhost/zf-tutorial/news/add
, controllerom je news
a akcia je add
. To umožňuje zoskupovať podobné akcie. Napr. controller news
môže obsahovať akcie current, archived
a add
. Zend Framework okrem toho podporuje systém modulov pre zoskupovanie controllerov, ale toto nie je dostatočné rozsiahla aplikácia aby sme to potrebovali využívať.
Zend Framework si rezervuje špeciálnu akciu nazývanú index
ako predvolenú (default) akciu. Takže pri požiadavke URL http://localhost/zf-tutorial/news/
sa vykoná práve index
akcia controllera news
. Zend Framework si okrem toho rezervuje predvolený názov controlleru, ak nie je poskytnuté žiadne meno controlleru. Nie je prekvapením, že je to opäť reťazec index
, takže po zadaní URL http://localhost/zf-tutorial/
sa vykoná akcia index
v controlleri index
.
V tomto tutoriáli nebudeme veci komplikovať funkciami ako prihlasovanie. Necháme si to pre ďalší tutoriál.
Nakoľko sme si definovali 4 stránky pre obsluhu albumov, zoskupíme si ich do jedného controlleru ako 4 akcie. Použijeme predvolený názov pre controller, pričom názvy akcií budú:
Stránka Controller Akcia
----------------------------------------
Home page Index Index
Add new album Index Add
Edit album Index Edit
Delete album Index Delete
Pekné a jednoduché.
</prelozeny-text>
Na tomto mieste tutoriál prerušíme a budeme pokračovať v ďalšej časti. Dôvodom je, že vygenerovanie článku zaťažuje server BH (to potrebuje nejaký CPU time), takže si nemôžem dovoliť napísať ľubovoľne dlhý článok. Obmedzil by som komfort ostatných návštevníkov BH. Už takto som dosť na hrane (zaujímal by ma názor admina, keď na článok klikne 20 ľudí naraz).
Ospravedlnujem sa za formu tabulkovych udajov, ale BH system neumoznuje pouzivat tabulkove HTML elementy. Co som testoval zobrazenie, ludia s rozlisenim 1024x768 budu mat dost rozsypany text, od 1280x1024 je to uz O.K.
----------------------
Ja len v dobrom.
formatovanie clankov riesim, je pravdepodobne, ze pribudnu nejake dalsie moznosti. inak, html tagy mozes pouzit v podstate lubovolne a potom napisat admin userovi, co to potom da zobrazovat vo "full html" mode. teoreticky podobne php
==
Don't buy drugs...Become a pop star and get them for free!
Ja len chcem reagovat na tie posledne vety. Moj clanok (cast serialu) ktory pisem uz par mesiacov ma zatial vyse 600 riadkov (v textovom editore kate pri maximalizovanom okne), takze este len to bude zataz na server :D
Inak pekny clanok, uz davnejsie som chcel vediet co je to zend framework :)
----------
tommyhot@hackingmachine:~$ microsoft &> /dev/null
srigi skusal si niekedy aj nieco ine ako zend? nechem byt ten co furt a vsade kritizuje ale za tie roky som si uz zvykol
zend ako aj v pripade php (dokazom je posledny navrh namespaces) nie je schopny urobit kvalitny a logicky kod, tento framework je vysmech fm logike. som rad ze si spokojny a ze si si dal namahu, ja ostatnym odporucam cakePHP alebo symfony
inak stastne a vesele :)
------------------------------
http://blog.synopsi.com
hmm zaujimave.. so zendom som pracoval dobre 4 mesiace a musim povedat ze ma SRACKOVU model vrstvu..
fakt tiez odporucam symfony, ktore vyuziva propel..