Framework
Z początku framework wygląda, jak każdy inny. Dostajemy do ręki bibliotekę z klasycznym podziałem na kontrolery, akcje i widokoszablony, Active Record, system formularzy, generator kodu oraz inne rzeczy, których moglibyśmy oczekiwać. Siadamy, na podstawie tutoriala generujemy parę modeli oraz szkielet aplikacji CRUD, po czym wypełniamy go resztą. Gdy ujrzymy pierwsze kawałki wygenerowanego kodu, odkryjemy pewną ciekawą rzecz. Jakiś czas temu pisałem, że nie ma frameworka PHP, który pod nazwą MVC faktycznie udostępnia MVC. Okazuje się, że nie do końca. Autorzy Yii jako jedyni chyba spojrzeli na diagram tego wzorca, co zresztą widać w dokumentacji pokazującej, że między widokiem i modelem zachodzi bezpośrednia komunikacja. Nie jest to uwzględnione bezpośrednio w API, lecz realizowane za pośrednictwem rozmaitych widgetów. Przyjrzyjmy się jednej z akcji w wygenerowanym kontrolerze CRUD:
public function actionAdmin() { $dataProvider=new CActiveDataProvider('Category', array( 'pagination'=>array( 'pageSize'=>self::PAGE_SIZE, ), )); $this->render('admin',array( 'dataProvider'=>$dataProvider, )); }
Wyświetlenie listy wierszy z bazy zazwyczaj wymaga korzystania ze stronicowania, sortowania danych po kolumnach oraz innych bajerów. W innych frameworkach cały ten kod ląduje w kontrolerze, a żeby było śmieszniej, niektóre frameworki nawet nie generują kodu z obsługą nawet najprostszych bajerków. Oznacza to, że jeśli chcemy dodać sobie w końcu stronicowanie, musimy jak idioci poprawić każdy kontroler z osobna. Nie jest to ani produktywne, ani zgodne z filozofią projektowania aplikacji. Tymczasem w Yii musimy jedynie stworzyć obiekt CActiveDataProvider, który odpowiednio opakowuje odpowiedni model, a w szablonie odpalić CRUD-owy widget:
<?php $this->widget('zii.widgets.grid.CGridView', array( 'dataProvider'=>$dataProvider, 'columns'=>array( 'id', 'title', 'body', 'productNum', array( 'class'=>'CButtonColumn', ), ), )); ?>
Jeśli stwierdzimy, że część akcji musi jednak inaczej to wyświetlać, po prostu piszemy własny widget CRUD i podmieniamy go, co jest o wiele szybsze i pozwala uniknąć wielu błędów.
Dodatkowe biblioteki
Składanie aplikacji z generowanych kontrolerów jest bardzo szybkie. Yii automatycznie zabudowuje w nich szkielet mechanizmu uprawnień, który można bardzo prosto dostosować do własnych potrzeb, a także generuje wszystkie potrzebne pliki. Wiele elementów udostępnionych jest jako modele, dzięki czemu ich obsługa jest w miarę jednolita. Podstawowymi rodzajami modeli są CActiveRecord oraz CForm. Pierwszy z nich reprezentuje oczywiście wiersz tabeli z bazy danych oraz posiada wbudowaną funkcjonalność formularza do zarządzania nim. Drugi pozwala tworzyć swobodne formularze, niezwiązane z konkretnym bytem (np. logowanie). Jeżeli tworzymy aplikację wielojęzyczną, możemy wykorzystać system tłumaczeń posiadający wbudowaną obsługę formatowania warunkowego. Poniżej pokazany jest przykład zastosowania:
Yii::t('kategoria', '1#W bazie jest jedna książka|n>1&&n<5#W bazie są {n} książki|n>4#W bazie jest {n} książek', array('{n}' => $number));
Wiele innych bibliotek można sobie doinstalować dzięki obszernej bazie rozszerzeń.
The Zyxist Kustomizer
Oczywiście jak to z frameworkami bywa, pierwszą rzeczą, którą na nich próbuję zrobić, jest coś, co je dokumentnie zagina. Yii sprawdza się świetnie przy tworzeniu aplikacji CRUD oraz stron o sztywnej, w miarę ustalonej strukturze, którą można zapisać na sztywno w kodzie (portal, aplikacja bazodanowa). Aplikację możemy dodatkowo podzielić na moduły posiadające własne kontrolery, widoki, modele oraz komponenty, jednak schody zaczynają się, gdy spróbujemy zbudować na nim konfigurowalną aplikację CMS. Tego typu projekt wymusza trochę inne działanie aplikacji, które niezbyt przystaje do sztywnego podziału na kontrolery i akcje. Tutaj kontroler musi załadować informacje z bazy, odnaleźć odpowiednie moduły, przekazać im sterowanie, a następnie odebrać wynik. Oczywiście nie można mieć wszystkiego, zatem siadłem sobie i stwierdziłem, że napiszę własny kontroler bazowy rozszerzający klasę CBaseController dostosowany do takiej konfigurowalnej struktury modułowej. Zaczęło być wesoło, gdy zorientowałem się, że wraz z tą klasą dostaję cały pakiet zupełnie niepotrzebnych mi metod do zarządzania... renderowaniem, osadzaniem widgetów, buforowaniem kodu HTML itd. I to jest kolejny z powodów, dla którego jestem wrogiem redukowania warstwy widoku do szablonów.
Jest jeszcze jedna mała niedogodność. Framework powstał za czasów PHP 5.2, przez co dubluje trochę funkcjonalności, która pojawiła się w wersji 5.3. Mowa tu o strukturach danych oraz o formatowaniu warunkowym w systemie tłumaczeń, które jest też wbudowane w nową bibliotekę Unicode. Ale to już takie czepiactwo pro forma - ciężko wymagać, by autorzy korzystali z czegoś, czego w momencie rozpoczęcia prac jeszcze nie było, a ponadto trzeba mieć na uwadze wsteczną kompatybilność.
Podsumowanie
Choć Yii też do końca nie zaspokoił moich wygórowanych wymagań odnośnie MVC, na pewno jest to perełka pośród frameworków, gdyż przynajmniej nie wmawia programistom głupot, że cała komunikacja z modelu do widoku musi iść przez kontroler. Do typowych zastosowań niewymagających korzystania z bardziej niskopoziomowego API jest jak znalazł. Warto się z nim zapoznać i zobaczyć czy taki styl pracy nam odpowiada.






Napisał Tuner w środę, 17 lutego 2010 o 14:18
Miło, że ktoś bliżej spojrzał na ten framework :)