Autorom Yii frameworku je Qiang Xue, čínsky programátor ktorý okrem iného stojí za PHP frameworkom PRADO. Verzia 1.0 bola vydaná 3.Dec 2008 po takmer ročnom vývoji. Na domovskej stránke o ňom autor vyhlasuje, že je rýchly, bezpečný a profesionálny, určený pre vývoj WEB 2.0 aplikácií. Stavia nad štandardným konceptom MVC, pričom obsahuje vlastné riešenie pre modelovú vrstvu s využitím patternu Active Record.
Je bohato vybavený a pritom veľmi kompaktný (light-weight), poskytne vám nástroje pre:
- abstraktný aj objektový prístup k databáze
- validáciu užívateľských vstupov (validátory sú spoločné pre formuláre aj Model)
- ACL
- i18n a l10n
- cache vrstva (aj fragment caching)
- transparentnú podporu komponentov jQueryUI (AJAX, serverový kód, widgety pre šablóny)
- podporu pre skiny a themy
- jednotkové a funkčné testy
- scaffolding pre automatické generovanie kódu
V neposlednom rade je treba spomenúť dokumentáciu, ku ktorej patrí vynikajúca užívateľská príručka, Wiki, API referenčná príručka alebo niekoľko tutoriálov. K štúdiu Yii je dostupná aj tlačená kniha Agile Web Application Development with Yii 1.1 and PHP5. Online pomoc je možné hľadať na oficiálnom fóre alebo na IRC. Yii má aj veľmi živý twitter kanál, na ktorom takmer každý deň pribudne niekoľko tipov a trikov, ktoré komunita zapísala do Wiki.
Framework až nezvykle tlačí vývojárov k využívaniu konzoly. V stiahnutom archíve sa prekvapivo nenachádza žiadny skeleton pre začatie nového projektu, pritom však framework vyžaduje pomerne striktnú adresárovú štruktúru. Nový projekt je preto nutné vytvoriť pomocou scaffoldingu – spustením konzolovej aplikácie v zložke s frameworkom:
$ cd /var/www/projectx/framework $ ./yiic webapp ../www_root
Tento príkaz pripraví skeleton nového projektu s niekoľkými Views a widgetmi pre dynamické menu a drobečkovú navigáciu
Adresárová štruktúra projektu v Yii vypadá takto:

Samotný kód aplikácie sa nachádza v zložke www_root/protected. Názvy pod zložiek nepotrebujú komentár. Zložka protected ma v kontexte projektu špeciálny význam – patrí pod jeden z aplikačných aliasov, konkrétne application. Aliasov je niekoľko, využívajú sa hlavne pri práci s filesystémom (napr. upload obrázkov). Filesystem cestu z aliasu získame kdekoľvek statickým volaním
Yii::getPathOfAlias(NAZOV_ALIASU);
Zoznam všetkých systémových aliasov:
| system | cesta k Yii frameworku |
|---|---|
| application | cesta k zložke protected (application’s base directory) |
| webroot | cesta k document_root webovej aplikácie, (zložka s index.php) |
| zii | cesta to knižnice zii (okrem iného jQuery UI komponenty) |
| ext | cesta k zložke pre 3rd party knižnice |
Metódy pre prácu s aliasmi dovoľujú pracovať s hierarchiou zložiek pomocou bodkovej konvencie. Napr. import konkrétnej triedy môžeme vykonať pomocou:
Yii::import('ext.Zend.Pdf.Color');
Yii::import('ext.Zend.Pdf.*'); // importuje celu zlozku
Yii používa jednoduchý autoloader, prehľadávané cesty sa nastavujú v konfiguračnom súbore (v prípade webovej aplikácie protected/config/main.php).
'import'=>array(
'application.models.*',
'application.components.*',
'application.extensions.*',
),
Statická trieda Yii predstavuje univerzálneho, všade dostupného pomocníka, ktorý umožňuje získať zaujímavé objekty kdekoľvek v projekte (dnes sa však už tento koncept považuje za prekonaný, do popredia vstupuje technika Dependency injection). Najčastejšie budete pravdepodobne využívať volanie Yii::app(), ktoré získa bežiacu aplikáciu. Webovú reprezentuje objekt CWebApplication, ktorý poskytuje napr. tieto properties (komponenty):
| request | CHttpRequest | obálka nad prišlým HTTP požiadavkom |
|---|---|---|
| session | CHttpSession | nízko úrovňová obálka nad PHP session |
| user | CWebUser | vysoko úrovňová obálka nad PHP session, abstrahuje návštevníka stránky |
| urlManager | CUrlManager | dvojsmerný URL router |
| clientScript | CClientScript | manažér JS a CSS |
Na tomto mieste spomeňme, že v Yii sú všetky triedy (okrem Yii) prefixované C (viď. vyššie). Obmedzí sa tak kolízia s vašimi triedami a triedami iných knižníc.
Nový projekt obsahuje vlastnú kópiu aplikácie yiic v zložke protected. Pre scaffoldovanie v rámci samotného projektu je nutné využívať tento! Aplikácia yiic poskytuje ešte niekoľko ďalších príkazov okrem webapp, stačí ju spustiť bez parametrov

- message – vyhľadá nepreložené frázy vo Views a vygeneruje prekladové súbory vo forme PHP arrays
- migrate – podpora pre databázové migrácie
- shell – interaktívny shell v bežiacom Yii projekte
- webapp – vytvorenie nového projektu
Za zmienku stojí príkaz shell, ktorý poskytuje vlastnú sadu príkazov:

Yii v tomto veľmi pripomína veľké frameworky ako Symfony alebo RoR a umožňuje pomerne mocné prototypovanie aplikácie. Pomocou niekoľkých príkazov v konzoli je možné vytvoriť jednoduché administračné rozhranie (CRUD nad tabuľkami), stačí správne nastaviť pripojenie k databáze v konfiguračnom súbore.
Ako sme už spomenuli, interaktívny shell beží v rámci Yii projektu, je teda možné spúšťať napr. metódy nad vašimi Modelmi. Samotné vytvorenie Modelu z existujúcej databázovej tabuľky a získanie záznamov z tabuľky je otázkou dvoch príkazov v interaktívnom shelli:

Scaffold automaticky pripravil aj podklady pre unit testovanie Modelu. Projekt je možné prototypovať aj pomocou webového rozhrania nazvaného Gii, ktoré je webovou kópiou interaktívneho shellu. Stačí len odkomentovať príslušnú sekciu v hlavnom konfiguračnom súbore, nastaviť heslo a otvoriť správnu adresu v browseri.
Ešte sa zastavíme pri konzoli. Yii umožňuje vytvárať vlastné konzolové aplikácie rovnako pohodlne ako tie webové. Konzolové controllery reprezentované potomkami CConsoleCommand predstavujú nové konzolové príkazy, ktoré pre vás spúšťa konzolový scafollder yiic:
<?php // protected/commands/NewsletterCommand.php
class NewsletterCommand extends CConsoleCommand
{
public function run($args)
{
if (empty($args)) {
die("nAvaiable command(s): send, prepare-newnn");
}
switch ($args[0]) {
case 'send':
echo "sending newslettern";
break;
case 'prepare-new':
echo "creating new newslettern";
break;
default:
die("nERROR! Wrong or no command specified. Avaiable command(s): send, prepare-newnn");
break;
}
}
}

ORM a formuláre
Ako sme už spomenuli vyššie, Yii disponuje vlastným ORM pre Modely. Využíva pattern Active Record – každý vytvorený Model zastupuje databázovú tabuľku. Nie je však úplne pravda, že Modely môžu byť iba databázového pôvodu. Pre generické Modely Yii ponúka triedu CModel, podstatne zaujímavejšie sú však odvodené typy: CActiveRecord a CFormModel. Pozrime sa najskôr na prvý.
CActiveRecord umožňuje klasické:
$application = new Application; $applicaion->name = 'Sample application'; $appliction->author_id = '4'; $application->save();
Je treba upozorniť, že pred uložením automaticky prebehne validácia Modelu (možné zakázať prvým parametrom metódy save()). Pravidla sú uložené v samotnej definícii triedy Modelu ako PHP array (v Yii je všetko konfigurovateľné uložené ako PHP array). Scaffolder pri vytváraní nového Modelu nastaví vhodné pravidlá na základe definície stĺpcov v databázovej tabuľke:
public function rules()
{
return array(
array('name, author_id', 'required'),
array('author_id', 'numerical', 'integerOnly'=>true),
array('name', 'length', 'max'=>120),
);
}
S pravidlami súvisia aj tzv. scenária Modelu. Modelu je možne oznámiť kontext, v akom sa má validovať. Napr. pri registrácii nového užívateľa, Modelu User nastavíme scenário insert, kedy sú vyžadované polia password a passwordRepeat. Naopak, keď užívateľ edituje svoj profil v administrácii, nevyplnené polia znamenajú, že užívateľ si nepraje meniť heslo a polia sa preto nebudú validovať. Modelu to oznámime nastavením scenária update. Validačné pravidlá môžu v takomto prípade vypadať takto:
public function rules()
{
return array(
array('email', 'required'),
array('password, passwordRepeat', 'required', 'on'=>'insert'),
...
);
}
Pohodlie programátora je dokonca zvýšené faktom, že hore uvedené dve scenária sú pre neho nastavované automaticky:
- pri inštancovaní Modelu sa nastaví
insert - pri načítaní Modelu z databáze sa nastaví
update
Nad procesom však samozrejme máte plnú kontrolu:
$user = new User('registration');
if ($user->validate()) {
// TODO
$user->setScenario('vote');
if ($user->validate()) {
// TODO
}
}
Pre viac detailov o validačných pravidlách si prosím naštudujte problematiku v užívateľskej príručke, kde okrem iného nájdete aj zoznam dostupných validátorov.
Pre načítavanie Modelov z DB poskytuje Yii celú plejádu find* metód. Najskôr však treba získať živú inštanciu Modelu:
$aplication1 = Application::model()->findByPk(1);
$aplications = Application::model()->findAll('author_id=:authorId', array(':authorId'=>4));
Všimnite elegantnú syntax techniky parameter binding. Pre pokročilejšie dotazovanie je dostupný tzv. query builder:
$c = new CDbCriteria;
$c->condition = 'author_id=:authorId';
$c->order = 'name DESC';
$c->params = array(':authorId'=>4);
$applications = Application::model()->findAll($c);
Relačné ORM
WEB 2.0 aplikácie zhusta pracujú s previazanými údajmi v databázach, preto podpora pre relačné vzťahy nesmie v Yii ORM chýbať. CActiveRecord podporuje 4 druhy relácií:
BELONGS_TO, objekt je vlastnený iným objektom, N:1, napr. aplikácia má jedného autoraHAS_MANY, objekt vlastní mnoho podradených objektov, 1:N, autor má mnoho aplikáciíHAS_ONE, špeciálny prípadHAS_MANY, kde nadradený objekt môže vlastniť iba jeden podriadený objektMANY_MANY, typický M:N vzťah, aplikácia môže byt vo viacerých kategóriách, kategória môže obsahovať mnoho aplikácií
Ak vaša databáza podporuje referenčnú integritu a mate správne nastavené FK’s, môžete sa spoľahnúť že scaffold processing Modelov nastaví vaše triedy správne (relačné vzťahy je potrebné zapísať do tried Modelov). V prípade MANY_MANY je pri scafoldingu krajných Modelov automaticky rozpoznaná väzobná tabuľka. Model pre túto tabuľku nie je potrebné vytvárať. Pre ukladacie mechanizmy bez podpory FK je možné väzby zapísať ručne:
public function relations()
{
return array(
'author' => array(self::BELONGS_TO, 'User', 'author_id'),
'tags' => array(self::MANY_MANY, 'Tags', 'applications_tags(application_id, tag_id)'),
);
}
Scaffolding predsa len urobí drobnú chybku pri generovaní tried – v relačnom pravidle, v druhom prvku (odkazovaná trieda) neustále vyplňuje plurál (Users)! Dajte si prosím na to pozor.
Toto v Modeli vytvorí virtuálne properties, ktoré svoj obsah získajú lazy, pri prvom prístupe k takejto relačnej property. Ak vyžadujete načítanie relačných údajov už pri fetchnutí hlavného objektu (objektov), Yii vám poskytuje techniku nazvanú eager loading:
$applications = Application::model()->with('author')->findAll();
Do kategórie vyšší dívči už potom možno zaradiť SELECT podľa relačného stĺpca:
$c = new CDbCriteria; $c->with = 'author'; $c->condition = "author.name='John Doe'"; $applications = Application::model()->find($c);
formuláre
Pre vývojára je najdôležitejšia možnosť definovať, vykresliť a spracovať formulár. Vynikajúca správa – v Yii je možné formuláre vykresľovať z inštancií CActiveRecord! Nemusíte ich teda nijako definovať. Dokonca ani vytvárať nejaké extra validačné pravidlá. Vďaka faktu, že formulár je reprezentácia Modelu vo View, má vývojár ušetrené množstvo práce. Postranným efektom toho je, že typ a vzhľad formulárového políčka je definovaný vo View šablone, tak ako je to najsprávnejšie. Príklad takej šablóny:
<div class="form">
<?php $form = $this->beginWidget('CActiveForm', $options = array('id'=>'applicationForm')); ?>
<div class="row">
<?php echo $form->labelEx($application,'name'); ?>
<?php echo $form->textField($application,'name'); ?>
<?php echo $form->error($application,'name'); ?>
</div>
<div class="row">
<?php echo $form->labelEx($application,'author'); ?>
<?php echo $form->dropDownList($application, 'author', $application->getAuthorsDLdata()); ?>
<?php echo $form->error($application,'author'); ?>
</div>
<div class="row buttons">
<?php echo CHtml::submitButton('save'); ?>
</div>
<?php $this->endWidget(); ?>
</div>
Upozorníme len na riadok s definíciou selectboxu (dropDownList). Vyžaduje naplniť PHP poľom so schémou value=>display. Takéto pole je najvhodnejšie získať zo samotného primárneho Modelu (alebo staticky z relačného Modelu):
Class Application extends CActiveRecord
{
...
public function getAuthorsDLdata()
{
$authors = Author::model()->findAll();
$out = array();
foreach ($authors as $author) {
$out[$author->id] = $author->name;
}
return $out;
}
...
}
Spracovanie formulára v Yii sa zvyčajne vykonáva v rovnakej akci, ktorá ho vykreslila. Vďaka tomu je vykreslenie validačných chýb prirodzené a nevyžaduje zbytočnú logiku.
Class SiteController extends CController
{
...
public function actionUpdateApplication($id)
{
$application = Application::model()->findByPk($id);
if (Yii::app()->request->getIsPost() && isset($_POST['Application'])) {
$application->attributes = $_POST['Application'];
if ($application->validate()) {
$application->save(false);
$this->user->setFlash('info', 'Update succeeded.';
$this->redirect(array('/site/updateApplication', 'id'=>$id));
Yii::app()->end();
}
}
$this->render('updateApplication, array(
'application'=>$application,
));
}
...
}
Za mierne neintuitívne a nemoderné možno považovať manuálne naplnenie Modelu prijatými údajmi priamo z $_POST. Napriek tomu je však operácia bezpečná a novými hodnotami su prepísané len polia, ktoré majú definované validačné pravidlá. Nestane sa tak, ze by útočník mohol podvrhnúť request, v ktorom posiela napr. ID záznamu, a ten tak prepísal. Ak by predsa len nastala potreba meniť propery Modelu bez definovaného validačného pravidla, označte pole ako safe vo validačných pravidlach.
public function rules()
{
return array(
...
array('id', 'safe'),
...
);
}
CFormModel
Ako sme už spomenuli vyššie, Modely nemusia mať len persitentné pozadie. Občas nastane potreba vytvoriť formulár bez akejkoľvek väzby na databázu, napr. formulár na vyhľadávanie. Takýto formulár je nutné manuálne definovať ako potomka CFormModel:
<?php
class SearchForm extends CFormModel
{
public $search;
public function rules()
{
array('search', 'required'),
array('search', 'lenght', 'min'=>3),
);
}
S takto definovaným formulárom potom pracujeme (vykreslenie, spracovanie) úplne rovnako ako s CActiveRecord, tak ako sme naznačili vyššie.
View šablóny, routovanie
Každý správny MVC framework obsahuje mechaniku vykresľovania View šablón a Yii nie je výnimkou. Implementuje klasické dvojfázové vykresľovanie zvnútra=>von, tj. šablóna-akcie=>layout. View šablónu sme si už ukázali pri vykresľovaní formulára. Mohli ste si všimnúť, že sa jednalo iba o klasické PHP značkovanie. Yii skutočne neposkytuje žiadny šablónovací jazyk a do vetvy 1.1 sa ani neplánuje. Nakoľko ani neimplementuje žiadny response objekt, nie je možné v šablónach využívať filtre. Dôležitým faktom je, že $this v šablónach ukazuje na aktuálny Controller. Môžeme tak aspoň z časti využívať helpre vo forme jeho metód. Existuje aj veľmi užitočný pomocník (helper container) – CHtml, ktorý obsahuje množstvo statických metód pre každodennú potrebu.
Najčastejšie v šablónach narazíte na potrebu vykresliť predané údaje a generovanie linkov na HTTP akcie. Predávanie údajov do šablóny sme mohli vidieť v príklade spracovania formulára, keď sme do šablóny predali inštanciu objektu Application. Pri vykresľovaní dynamických údajov je treba dbať na bezpečnosť a údaje pred vypísaním ošetriť:
<?php echo CHtml::encode($application->name); ?>
Generovanie linkov z routra je možné riešiť dvojako:
<a href="<?php echo $this->createUrl(ROUTA, $urlParams=array()); ?>">text linku</a>
alebo
<?php echo CHtml::link(TEXT_LINKU, array(ROUTA, $urlParams) $htmlOptions=array()); ?>
Routu predstavuje destinácia, na ktorú link mieri vo forme /modul/controller/akcia. Modul nie je povinné uvadzať, ak nepoužívate modulárnu aplikáciu alebo nechcete opúšťať aktuálny modul. Príklad linku aj s dodatočnými parametrami:
<a href="<?php echo $this->createUrl('/news/create', array('lang'=>$this->lang)); ?>">pridať novinku</a>
Takéto vytváranie URL bude správne reflektovať zmeny vo vašich routovacích maskách. Konfigurácia masiek je uložená v protected/config/main.php, ale jej popis je nad rámec článku. V užívateľskej príručke nájdete vyčerpávajúci výklad problematiky.
Widgety
Aj s widgetom sme sa stretli pri vykresľovaní formulára. Widget si možno predstaviť ako vykresliteľný blok s vlastnou akciou a šablónou. Do View šablóny sa umiestni volaním:
<?php $this->widget('FooWidget', $properties=array('uid'=>$user->id)); ?>
Najjednoduchší widget by potom mohol vypadať
<?php
class FooWidget extends CWidget
{
public $uid;
public function run()
{
$this->render('fooWidget', array(
'user' => User::model()->findByPk($this->uid)
));
}
}
šablóna
<div id="fooWidget"> <?php echo CHtml::encode($user->name);?> </div>
Widgety je vhodné umiestniť do zložky protected/widgets, šablóny prídu do protected/widgets/views. V konfiguračnom súbore alebo inde v projekte je potom nutné zaistiť ich import do aplikácie.
Zhrnutie
Yii je veľmi bohatý framework. V tomto sumáre sme pokryli len základné vlastnosti a schopnosti, ktoré sú nutné pre prvé kroky s frameworkom. Vyznačuje sa kompaktnosťou, výkonom ale hlavne výborne spracovanou dokumentáciou. Vývoj Yii je veľmi živý a narastajúcu popularitu dokazuje aj umiestnenie v nedávnom experimente, kde bola určená popularita webových frameworkov podľa množstva topicov na Stack Overflow.
Za nevýhody možno považovať absenciu šablónovacieho jazyka, nepoužívanie najmodernejších techník (response objekt, statická trieda Yii), ale aj neprehľadné kombinovanie anglických a čínskych topicov vo výsledkoch vyhľadávania na oficiálnom fóre.
Yii si istotne zaslúži pozornosť a istotne sa o svoju pozíciu pobije. Nech aj tento článok prinesie jeho väčšiu popularitu v česko-slovenských kotlinách.






Přehled komentářů