Agavi jest frameworkiem MVC napisanym w PHP5. Jest on stosunkowo słabo znany w środowisku programistów PHP. Przyczyną tego jest to iż dopiero od niedawna dostępne jest Agavi oznaczone wersją 0.11, które ma zamrożone API. Jednak przede wszystkim framework ten nadal nie posiada dokumentacji, co właściwie go dyskwalifikuje. Developerzy Agavi obiecują że dokumentacja się wreszcie pojawi, ja tymczasem postaram się częściowo załatać dziurę serią artykułów o tym świetnym frameworku.
Tak jak pisałem we wstępie - Agavi jest frameworkiem którego działanie opiera się na wzorcu projektowym - MVC - Model View Controller.
Wg. tego wzorca aplikacja dzieli się na 3 części. Nie zagłębiając się w szczegóły odpowiednie warstwy odpowiadają za
W Agavi znajdują się dodatkowo akcje które to są wywoływane przez kontroler. Akcja natomiast może posiadać kilka widoków.
Zacznijmy od utworzenia struktury folderów na naszym serwerze. Składać się na nią będą:
Możemy ściągnąć najnowszą wersję Agavi ze strony frameworka. W momencie pisania artykuły najnowszą wersją jest 0.11.1. Po ściągnięciu, należy rozpakować paczkę, zmienić nazwę folderu na “agavi” i przenieść go do folderu libs.
Następnie przygotujmy sobie generatora. Skrypt ten używa phing’a, aby go zainstalować należy wykonać następujące komendy w konsoli (musisz mieć skonfigurowany pear).
Skopiujmy skrypt agavi.bat-dist, który znajduje się w /libs/agavi/etc, do /dev zmieniając jego nazwę na agavi.bat. Używając naszego ulubionego edytora tekstowego zmieńmy ścieżki znajdujące się w skrypcie:
Tak wyglądają ścieżki w moim przypadku. Pierwsza wskazuje plik skryptu phing, druga źródła agavi.
Mając już gotowe narzędzie możemy uruchomić konsole i wykonać skrypt agavi.bat:
Skrypt będzie nas pytał o różne ciekawe rzeczy. My grzecznie za każdym razem wciskamy enter. Po ok 45 sek. generator powinien poinformować nas że zakończył swoją pracę sukcesem, natomiast my po uruchomieniu aplikacji - http://localhost/agavi_application/pub/ powinniśmy zobaczyć logo agavi. Oznaczać to będzie że wszystko generator stworzył za nas pierwszą aplikację opierającą się na Agavi.
Aplikacje pisane na Agavi mają budowę modularną. Każdy moduł składa się z akcji. Akcja może mieć kilka widoków, widok natomiast może używać różnych szablonów. Przykładowo: moduł News, posiada akcję Add, która posiada widoki Input (formularz dodawania newsa) oraz Success (wiadomość o dodaniu newsa).
Tak w dużym skrócie wyglądają moduły. Moduły dodatkowo mogą posiadać własną konfigurację, pliki validatora, lub inne biblioteki które są używane przez moduł.
Stwórzmy sobie przykładowy moduł Notes, który będzie modułem notek bloga. Wygenerujmy sobie ten moduł używając generatora agavi:
Generator będzie pytał nas o:
Generator powinien stworzyć za nas wszystkie foldery, pliki z szablonami klas, oraz puste pliki szablonów. Pozostaje nam teraz dopisać logikę aplikacji.
Agavi jest frameworkiem który w dużym stopniu opiera się na konfiguracji. Konfiguracja znajduje się w plikach XML, składa się na nią 13 podstawowych plików oraz dodatkowe pliki które może posiadać każdy z modułów. Ilość plików na początku może przerażać, jednak zapewniam że gdy dobrze poznamy ten framework, konfiguracja stanie się bardzo prosta i intuicyjna. Generator stworzył nam domyślną konfigurację i na niej będziemy się opierać. Zmienimy jedynie 4 pliki.
Ustawiamy akcję Index modułu Notes jako domyślną.
oraz włączamy komponent bazy danych:
Deklarujemy driver którego będziemy używać (w naszym przypadku PDO ale nic nie stoi na przeszkodzie abyś użył Propela, Doctrine lub cokolwiek innego) oraz dane potrzebne do nawiązania połączenia z bazą danych.
Plik z drogami. Zadeklarowaliśmy 3 scieżki. Pierwsza zostanie wybrana, gdy adres będzie wyglądał np. tak:
http://strona.pl/notes/123/html. Wykonana zostanie wtedy akcję ShowOne modułu Notes, przekazując parametr id o wartości 123. Druga pokaże nam formularz dodawania notki, a trzecia domyślną akcję.
W sekcji layouts, dodajemy jedną warstwę. Dekorator, czyli nasz “główny” szablon.
Pisanie aplikacji zaczniemy od modelu. Zaimplementujemy w nim metody które będą potrzebne dla akcji/widoków. Będą to metody: getRecent (zwrócenie ostatnich kilku notek), getById (zwrócenie notki o danym id) oraz save (zapis):
Tak wygląda nasz model. Myślę że zbytnio nie ma co się rozpisywać, są to podstawowe operacje na baze danych używając PDO.
Wygenerowane akcje mają obszerny komentarza. Warto go przeczytać i zapamiętać wskazówki w nim zawarte. Oprócz komentarza (po przeczytaniu możemy go wywalić ;) mamy jedną metodę: getDefaultViewName, zwraca ona domyślny widok który ma być wykonany jeżeli nie wskazano innego.
Najważniejszymi metodami akcji są metody executeRead oraz executeWrite. Są one wykonywane odpowiednio gdy wysłane są dane metodą GET i POST. Można zaimplementować jedną metodę - execute - w której ręcznie sprawdzali byśmy sobie skąd otrzymujemy dane. Nie jest to zalecane rozwiązanie jednak może zaistnieć sytuacja kiedy będziemy musieli z tej możliwości skorzystać. Wszystkie z tych 3 metod muszą zwrócić nazwę widoku który ma być wykonany. W przeciwnym wypadku nie zostanie wykonany żaden widok.
Jeżeli chodzi o naszą małą aplikację, a właściwie nasz jeden mały moduł to interesuje nas jedynie akcja Add. Inne akcje nie będą posiadały żadnej logiki. Będą jedynie zwracać widok, ten natomiast będzie prezentował dane pobrane od modelu.
Akcja Add domyślnie będzie uruchamiać widok Input, który będzie zawierał formularz. Jeżeli jednak zostaną przesłane jakieś dane metodą POST to zostanie wywołana metoda executeWrite.
Oto jak będzie wyglądać nasza akcja:
Kod bardzo prosty. Pobranie modelu, następnie wywołanie metody save, podając jako argument tablicę z danymi z formularza ($rd jest obiektem typu AgaviRequestDataHolder, są tam przechowywane dane z requestu)
Została nam ostania warstwa aplikacji, warstwa prezentacyjna czyli widok. W tym przypadku pomijamy widoku akcji Add, ponieważ nie potrzebujemy wciągać żadnych danych. Pokażemy jedynie formularz (Input) lub wiadomość o tym że dodano wiadomość (Success). Tak będą natomiast będą wyglądać widoki:
Są one prawie takie same. Różnią się one jedynie metodą modelu którą wykonujemy. W widoku ShowOne pobieramy z modelu jedną notkę o id którego wartość bierzemy z requestu, tam natomiast trafiło z routera, czyli z adresu url :)
Pozostało nam już tylko napisanie szablonów. Zacznijmy od głównego szablonu, czyli Master.php który musimy utworzyć w app/templates:
Ustawiając Master.php jako dekorator, wszystko co zwróci widok dane akcji (html), będzie później dostępne poprzez zmienną $inner. Szkielet strony wtedy trzymamy w Master.php a w miejscu, gdzie treść będzie sie zmieniać wyświetlamy zawartość $inner.
Nad szablonami myślę że nie ma za bardzo co się rozwodzić. Zwykły HTML, wyświetlający dane otrzymane z widoku.
W kilku szybkich krokach, nie zagłębiając się w szczegóły, stworzyliśmy bardzo prostą aplikację. Coś w stylu “Jak napisać bloga w 15 minut” używając mojego kochanego frameworka ;) Notka ta miała na celu bardziej zachęcić do zainteresowania się Agavi, niż szczegółowo opisać cały framework. Wszystko w swoim czasie ;)
Polecam przejrzeć jeszcze raz kod aplikacji (teoretycznie powinna ona działać, po uruchomieniu ;) w aby lepiej zrozumieć zasadę działania. Warto również zajrzeć do przykładowej aplikacji znajdującej się w paczce Agavi w folderze samples.
Komentarze
Bardzo ładnie @strzałku, tylko, czy od pewnego czasu nie przyjęło się, że w layerach używa się $inner zamiast slotu?
I kosmetyka: “<base href=”getBaseHref(); ?>” />”
Pozdrawiam, Alan.
Hmmmm, blog uciął znacznik zamykający “base”…
Bardzo się cieszę, że poruszyłeś temat Agavi. Jest to framework który prezentuje nieco inne podejście niż istniejące rozwiązania, w szczególności Zend Framework czy Symfony. Z jednej strony wiele wyniósł z Mojavi, z drugiej developerzy dodali gro możliwości, które sprawiają że praca jest rzeczywiście przyjemnością. Wystarczy wspomnieć konfigurację z użyciem XLink, wsparcie dla SOAP, rozbudowane mapowanie adresów (bije na głowę każde, które znam) i na końcu - najlepsze - Form Population Filter. :)
Artykuł bardzo fajny. Tak trzymaj!
Pozdrawiam,
Łukasz
Z tym kolorowanie kodu i w ogóle wklejaniem kodu w notce i komentarzach coś jest nie tak. Jak będę miał chwile powalczę z tym.
LBO: Racja. Nie wiedziałem że tak można, a jest dostępne to już od jakiegoś czasu (ticket #655). Zmieniłem w notce. Nadal jednak można odwoływać się “po staremu” czyli używając slotów.
Bardzo fajny artykuł. Szkoda że już od bardzo dawna nie miałem czasu na programowanie z użyciem tego frameworka.
Mam nadzieję że to nie ostatni artykuł na temat Agavi :)
Hej strzałku przyjrzałem się jeszcze raz i czy uważasz, że pobieranie danych w widoku to dobry pomysł?
Co zrobisz w przypadku błędu w modelu?
Wiem, że to tylko taka pokazówka, ale dobrze uczyć czytelników dobrych nawyków od samego poczatku.
dodatkowo: php specjalnie do zastosowania takiego jak w widoku udostepnia dodatkową notację bez klamerek.
To samo tyczy sie innych konstrukcji np. “if :”, “endif” - kod jest czytelniejszy.
Cholera zjadło mi kod php.
Pisałem dokładnie o tym: http://php.net.pl/manual/pl/control-structures.alternative-syntax.php