Oto kolejny wpis dotyczący frameworka PHP jakim jest Kohana. Udało się nam już zainstalować Kohanę oraz nakazać jej generowanie przyjaznych linków. Nadszedł więc czas na zapoznanie się z budową Kohany. Poznamy jej strukturę katalogów i plików oraz budowę plików składających się na aplikację.
Struktura plików
Kohana wykorzystuje wzorzec projektowy Model-View-Controller (MVC). Nie będę przedstawiał zalet i wad takiego rozwiązania (które jakby nie patrzeć stało się bardzo popularne), ponieważ chcę uniknąć wojny w komentarzach. ;) Struktura katalogów Kohany przedstawia się następująco:
- /application
- /cache
- /config
- /controllers
- /helpers
- /hooks
- /i18n
- /libraries
- /logs
- /models
- /views
- /modules
- /system
Pogrubioną czcionką zaznaczyłem katalogi, które zawierają składniki MVC. To do nich będziemy zaglądać najczęściej. Katalog /system zawiera "silnik" frameworka. Są tam też wszystkie domyślne pliki konfiguracyjne (katalog /system/config).
Modele
Modele służą do przetwarzania danych. Ich zadaniem jest walidacja przekazanych danych, wykonanie na nich odpowiednich operacji i zwrócenie ich spowrotem do kontrollera. Do czego więc może służyć model? Np. do pobrania, dodania, usunięcia lub edycji newsów (lub pojedyńczego newsa), listy użytkowników, postów forum, etc. Najprawdopodobniej korzystać będziemy w nich z bazy danych. Każdy model zawiera zdefiniowane pole $this->db zawierające obiekt bazy danych. Do budowania zapytań pomocna będzie nam dokumentacja. Wyniki zapytania są zwracane jako obiekt (chociaż można wybrać zwracanie tablicy => result_array(FALSE)), które przetwarzamy za pomocą pętli foreach. Modele znajdują się w katalogu /application/models, a ich nazwy plików muszą być pisane z małych liter (jako separatora używaj podkreślenia). Oto szablon każdego modelu (chociaż można rozszerzać dany model z każdego innego):
<?php defined('SYSPATH') or die('No direct script access.'); class Jakis_model_Model extends Model { function __construct() { parent::__construct(); } } ?>
W tym przykładzie plik, zawierający taką treść musi posiadać nazwę "jakis_model.php". Nazwa klasy musi posiadać na końcu sufiks "_Model". Modele wywołujemy w kontrolerach po prostu inicjując nową klasę. Np.:
$model = new Jakis_model_Model;
Widoki
Służą do prezentacji treści. Jest to tak zwana warstwa prezentacyjna. Służy ona oddzieleniu kodu PHP od HTML (chociaż w Kohanie nie do końca udało się tego dokonać). Widok zawiera szablon, do którego podstawiane są przekazane mu treści i wyświetla go. Aby zainicjować widok należy skorzystać z klasy View:
$widok = new View('nazwa_widoku');
Wywołanie tej klasy spowoduje załadowanie widoku "nazwa_widoku.php" z katalogu "/application/views". Sam z siebie jednak sie nie wyświetli, dlatego należy zrobić to samemu za pomocą metody "render()":
echo $widok->render(FALSE); $widok->render(TRUE);
Powyższy kod wyświetli dwukrotnie zawartość podanego pliku. Parametr metody render decyduje o tym, czy widok ma być "echowany" czy tylko zwracany (i przekazany np. do echo :)). Musimy jednak pamiętać, że render() musi być wywołany na samym końcu manipulacji na widoku! Jak zatem sprawić, by w widoku wyświetlały się dane przydzielane dynamicznie przez kontroler? Z pomocą przychodzi nam metoda "set()", która przyjmuje dwa parametry: nazwę zasobu (pod zmienną o takiej nazwie będą się znajdować dane w widoku) oraz dane jakie chcemy do niej przypisać. Zatem kontynuując przykład:
$widok->set('aktualna_data', date('d.m.Y', mktime()));
Po tym zabiegu pod zmienną $aktualna_data będzie zawarta... data. :) A używamy jej po prostu ją wyświetlając:
<h1>Testowy widok</h1> <p>Dzisiaj jest: <?=$aktualna_data?></p>
Użyliśmy tutaj skróconej formy polecenia echo, która wygląda na bardziej czytelną, a działa tak samo. Wynik wszystkich powyższych działań powinien być chyba znany. :)
Kontrolery
Kontrolery odpowiadają za kontrolę całej aplikacji. Decyduje o tym co będzie się dziać po jego wywołaniu. Jego zadanie polega najczęściej na pobraniu od modelu danych i przekazanie ich widokowi. Tak wygląda szablon kontrolera, którego nazwa pliku to "jakis_kontroler.php":
<?php defined('SYSPATH') or die('No direct script access.'); class Jakis_kontroler_Controller extends Controller { function __construct() { parent::__construct(); } function index(){ } } ?>
Wygląda podobnie jak model, prawda? Istnieje jednak kilka różnic. Po pierwsze sufiks nazwy klasy to "_Controller". Po drugie pojawiła się nam nowa podstawowa metoda - index(). Jest ona wywoływana gdy do nazwy kontrolera w adresie nie zostanie dołączona żadna metoda. W kontrolerach łączymy naszą wiedzę o modelach i kontrolerach.
Podsumowanie
Skoro już wiemy jak zbudowana Jest Kohana, możemy już zacząć pisać własne aplikacje. :) W następnej części dowiemy się jak zbudować naszą pierwszą, praktyczną aplikację, która będzie wykorzystywać jak najwięcej użytecznych elementów frameworka. Użyjemy bazy danych, pomanipulujemy na tekście, zabawimy się formularzami, przygotujemy logiczny system szablonów, a przede wszystkim wyłamiemy się nieco od przedstawionych powyżej zasad po to, by pisało się jeszcze przyjemniej. :)
framework
Autorem bloga jest Mariusz "marines" Kujawski. Poświęcony jest on programowaniu w językach webowych (PHP), tworzeniu stron (XHTML/CSS), systemom operacyjnym oraz przeróżnym nowinkom z sieci. 

Mała literówka.
Szkoda, że przy modelach nie wspomniałeś o ORM.
Masz zamiar napisać cały cykl tutoriali o Kohana?
dzieki, poprawione. IMO ORM obsysa. coś tam będę od czasu do czasu pisał. :) jak napisałem, że wkrótce napiszę coś dalej to na pewno napiszę co najmniej jeden post :D
„warstwa prezentacyjna. Służy ona oddzieleniu kodu PHP od HTML” pozwolę się nie zgodzić z tym stwierdzeniem (i zwaleniem winy na FW). Widok ma za zadanie oddzielić warstwę prezentacji od logiki aplikacji. I to jest tu realizowane w 100% podobnie jak w innych FW.
nrm, poniekąd to miałem na myśli :)
chore nazwy kontrolerow i modeli :P
po co dawać nazwa_kontroler_Conteroller ?
lepiej wygląda Nazwa_Controller ;)
i toroche namieszałeś początkującym z tym widokiem ;)
ale ogólnie ok :)
pozdrawiam
mariuszw, równie dobrze mogłem sobie go nazwać Ekstra_kontrolerek_Controller” ;] mam nadzieję, że każdy domyślił się, że to tylko przykład :P
na rzeczywistych przykladach lepiej sie uczy, wiec czekam na kolejna czesc :) Np.: znacznie lepiej brzmi Book_Model niz jakis_model_Model.
Co do ORM to jestem ciekaw co bedzie nowego w ORM2 bo w 1 i tak w wiekszosci kodu korzystalem z $this->db
@nexik: O zmianach przeczytasz na blogu Learning Kohana i w tym „changeset”:http://trac.kohanaphp.com/changeset/3021
Jako początkujący z Kohaną, czekam na jakieś ciekawe przykłady (jak jeden z kolegów wyżej nadmienił – rzeczywiste :) )
jako wszystkowiedzący, czekam na czas (rzeczywisty)
Kohana - instalacja i konfiguracja nie jest trudna
Skoro dokonałam już wybory frameworka pora go zainstalować. Przecież nie ma nic ciekawego ani zabawnego w uczeniu się nowego narzędzia “na sucho”. Trzeba mieć co popsuć, żeby zdobyć choćby minimalna wiedzę. A że w tyle głowy c...
czekamy na kolejnego newsa dotyczącego kohany ;]
Super artykuł, czytam już nasty poradnik tego typu i mogę powiedzieć, że jest to jeden z lepszych.
Pozdrawiam i oczywiście czekam na dalszy rozwój wydarzeń.
Cy kohana pozwala na wielopoziomową strukturę, jak np zend framework, typu modules/controller/action?
controller/action działa, ale przy wielopoziomowych się a tutorialale i dokumentacja nie wspoinają nic otym
nie wiem jak to wygląda w Zend Framework, ale domyślam się, że chodzi ci o organizowanie kontrolerów w grupy. z tego co pamiętam można. kontrolery można organizować w katalogi i odwoływać się do nich uwzględniając ścieżkę np. /kat1/kat2/controller/action
Potrzebne są do tego jakieś ustawienia/przekierowania w routingu lub .htaccess?
do przyjaznych linków są oczywiście potrzebne reguły w .htaccess, ale wywoływanie kontrolerów z katalogów działa bez niczego. dawno nie zaglądałem do Kohany, a widziałem, że wyszły nowe wersje, więc przepraszam z góry jeżeli się mylę (a mam nadzieję, że nie ;)).
Dzięki za info, będę szukał dalej
w kohana sam decydujesz o budowie adresu url, domyslnie jest to <controler><action><id>....<idX>