Witaj, Gościu O nas | Kontakt | Mapa
Wortal Forum PHPEdia.pl Planeta Kubek IRC Przetestuj się!

Frameworki dla PHP, czyli wydajne tworzenie aplikacji

MVC

Wiemy już, czym są frameworki, gdzie mogą być pomocne i na jakie problemy możemy natrafić wykorzystując je do tworzenia naszych aplikacji. Jeśli zastanawiacie się, jak może być zbudowany framework, zdradzę Wam mały sekret: nad problemem tym głowiło się i ciągle głowi wiele osób na całym świecie. Efektem licznych prób, błędów i teoretycznych rozważań są tzw. wzorce architektoniczne opisujące sposób konstruowania aplikacji danego typu. Nie są to gotowe biblioteki, tylko zasady i wskazówki wynikające z praktycznych doświadczeń.

W budowaniu ogólnej architektury złożonych aplikacji WWW najczęściej wykorzystuje się wzorzec architektoniczny MVC (ang. Model-View-Controller). Wytyczne zawarte w tym wzorcu mówią, jak podzielić aplikację na trzy logiczne, luźno powiązane ze sobą warstwy: modelu, widoku i kontrolera. Najważniejszą zaletą wynikającą z zastosowania MVC jest uporządkowanie budowy aplikacji oraz całkowite oddzielenie prezentacji (widok) od danych (model) i sposobu ich pobierania (kontroler).

Przyjrzyjmy się bliżej poszczególnym warstwom MVC:

  • model (ang. model) - warstwa obiektów biznesowych oraz dostępu do danych, które tworzą te obiekty. Model to obiekty związane wyłącznie z dziedziną, dla której tworzymy aplikację,
  • widok (ang. view) - definiuje, w jaki sposób zaprezentować obiekty z warstwy modelu oraz elementy interfejsu użytkownika. Odpowiada za prawidłowe sformatowanie danych z modelu w zależności od sposobu prezentacji (np. przeglądarka WWW lub PDF),
  • kontroler (ang. controller) - jest "dyrygentem", który w odpowiedzi na akcje użytkownika pobiera obiekty z modelu i przekazuje je do wybranego widoku.

Rysunek 1. Warstwy MVC i ich powiązania

Listing 1. Fragment skryptu z wymieszanymi warstwami MVC

<?php
// połączenie z DB
$link = mysql_connect("localhost", "root", "")
    or die("Nie mogę połączyć się z DB : " . mysql_error());
mysql_select_db('newsdb') or die("Nie mogę wybrać DB!");

//pobranie danych
$query = "SELECT * FROM my_news";
$result = mysql_query($query) or die("Błąd zapytania : " . mysql_error());

//pobieranie i prezentacja danych
echo "<table border='1'>\n";
while ($line = mysql_fetch_array($result, MYSQL_ASSOC)) {
    echo "\t<tr>\n";
    foreach($line as $col_value) {
        echo "\t\t<td>$col_value</td>\n";
    }
    echo "\t</tr>\n";
}
echo "</table>\n";

//rozłączenie z DB
mysql_free_result($result);
mysql_close($link);
?>

Najważniejszą korzyścią z zastosowania MVC jest całkowita separacja danych (i reguł nimi rządzących) od sposobu ich prezentacji. Dzięki temu te same obiekty (np. listę newsów) możemy prezentować w przeglądarce WWW jako PDF czy np. RSS i to bez zmiany logiki związanej z pobraniem czy przetworzeniem tej listy!

Aby taka separacja była możliwa, obiekty warstwy modelu nie mogą być świadome sposobu, w jaki zostaną zaprezentowane. To warstwa widoku, wiedząc z jakimi obiektami ma do czynienia, może je pokazać. Z drugiej strony, widok jedynie prezentuje wcześniej przygotowane dane: przetworzenie zapytania i pobranie odpowiednich wartości to zadanie kontrolera. Wszystkie te zależności można rozrysować w postaci diagramu widocznego na Rysunku 1.

Jak w praktyce wykorzystać świeżo zdobyte wiadomości? Na Listingu 1 przedstawiamy typowy przykład kodu, bazujący na oryginalnej dokumentacji PHP.

Zwróćmy szczególną uwagę na fragment kodu związany z pętlą while. Oprócz pobrania danych o wiadomościach (działanie na modelu), jednocześnie je wyświetlamy (widok). W jednej sekcji programu wymieszane są warstwy modelu i widoku. Zmiana sposobu prezentacji pociągałaby za sobą konieczność zmian w logice aplikacji. Gdybyśmy teraz chcieli te same wiadomości zaprezentować jako RSS (inny widok), musielibyśmy skopiować też całą pętlę. To oczywiście duplikacja kodu odpowiedzialnego za pobieranie danych.

Spróbujmy teraz zaradzić zidentyfikowanym problemom wykorzystując wzorzec MVC i separując model od widoku. Na Listingu 2 przedstawiliśmy oddzieloną część związaną z prezentacją i danymi. Taka mała zmiana istotnie wpływa na elastyczność naszej aplikacji. Fragment związany z widokiem łatwo wydzielić do osobnego pliku. Wtedy moglibyśmy włączać (include) odpowiedni skrypt z opisem sposobu prezentacji w zależności od końcowego urządzenia, na jakim oglądany jest serwis. Listing 3 jest przykładem wykorzystania tych samych danych do wygenerowania RSS.

Widok został oddzielony, możemy zająć się teraz warstwą modelu. Najpierw fragment związany z pobieraniem i przekazywaniem danych przeniesiemy do osobnych klas ( Listing 4). Pozwoli nam to wielokrotnie wykorzystywać obiekty modelu w różnych miejscach aplikacji (np. w prezentacji wiadomości na stronie WWW i w module administracyjnym). Zarówno dostęp do danych (klasa News- ModelDao) jak i metody obiektu (np. News- Model::isValid()) zostały wydzielone do osobnej warstwy. Dzięki temu fragment programu związany z interakcją z bazą danych znajduje się w dokładnie jednym miejscu. Nie straszne nam teraz zmiany nazw tabel. Podobnie ma się sprawa z obiektami klasy NewsModel: jeśli zmienią się zasady, według których uznajemy wiadomość za dostępną, będziemy musieli zmodyfikować tę logikę tylko w jednym miejscu. Gdyby wszystkie opisane zasady zakodować bezpośrednio w PHP czy zapytaniach SQL, to jakakolwiek zmiana oznaczałaby potencjalną konieczność przejrzenia i poprawienia wielu skryptów.

Ostatnią nieomówioną jeszcze warstwą MVC jest kontroler. Ogólnie, zadania kontrolera polegają na analizowaniu zapytania użytkownika i na podstawie tej analizy:

  • pobraniu odpowiednich obiektów modelu,
  • wybraniu odpowiedniego widoku i przekazaniu do niego wcześniej wybranych obiektów.

Omówione przykłady jasno wskazują korzyści płynące z zastosowania MVC. Niestety, nie ma róży bez kolców: elastyczność aplikacji okupiliśmy jej większym skomplikowaniem.

Listing 2. Wydzielenie widoku ze skryptu widocznego na Listingu 1

<?php
...
// połączenie z DB i pobranie
// danych - jak na Listingu 1
$result_arr = array();
while ($line = mysql_fetch_array($result, MYSQL_ASSOC)) {
    $result_arr[] = $line;
}
...
// rozłączenie z DB
...
?>
<table border='1'>
<?php foreach($result_arr as $line) {
    ?>
    <tr>
    <?php foreach($line as $col_value) {
        ?>
        <td><?php echo $col_value;
        ?>
        </td>
    <?php }
    ?>
    </tr>
<?php }
?>
</table>

Listing 3. Te same dane co na Listingu 2 - inna prezentacja.

<?php
include("class.myRSS.php");
$myRSS = new myRSS;
$myRSS->channelTitle = "Framework news";
$myRSS->channelLink = "http://www.phpsolmag.org";
$myRSS->channelDesc = "Framework news";
foreach($result_arr as $news)
{
    $myItem = new myRSSItem();
    $myItem->link = 'http://www.phpsolmag.org/news/' . $news['news_id'];
    $myItem->title = $news['news_title'];
    $myItem->description = $news['news_text'];
    $myRSS->addItem();
}
header("Content-type: text/xml");
echo $myRSS->getOutput();
?>
Informacje na podobny temat:
Wasze opinie
Wszystkie opinie użytkowników: (11)
Adam
Czwartek 14 Styczeń 2010 6:22:02 pm - pp-layouts <a.lyskawa_at_gmail.com>

A już myślałem, że jestem szaleńcem rozwijając własny framework. A robię tak dlatego, że wychodzi mi zawsze szybciej napisać brakujący komponent X niż nauczyć się od podstaw nowego frameworka. Do tego jeszcze ta siła przyzwyczajeń. Byłbym chory gdybym miał na przykład mieszać php z html w jednym pliku, a np w ZF to norma.

Fajny art
Piątek 09 Styczeń 2009 10:04:20 am - uve

Fajny art, tylko nie rozumiem jednej rzeczy.

Co jest zawarte w klasie newsmodel.clsss.php ?

Pozdr.

pdf
Wtorek 06 Styczeń 2009 1:40:05 pm - yaotzin <yaotzin1_at_o2.pl>

PDF'a dajcież ...

Art
Piątek 08 Sierpień 2008 12:29:47 pm - Joachim Peters <edaroo_at_gmail.com>

Fajny art, na poziomie :)

Wersja do wydruku
Wtorek 30 Październik 2007 4:09:24 pm - reddy

A czy jest gdzies wersja do wydruku (np. PDF lub calosc na jednej stronie)? Wygodniej czytac z kartki :)

;)
Środa 15 Sierpień 2007 8:41:40 pm - carbolymer

Ciężki artykuł o ciężkim temacie. Listingi zbyt porozrzucane, czasem nie można odnaleźć klas o których jest mowa w tekście. Jest parę literówek w kodzie. Ogólnie jest dobrze.

Dobry artykul
Czwartek 04 Maj 2006 1:45:52 am - SzajbuS <szajbus_at_rambler.com.pl>

Listingi i rysunki troche zle umiejscowione w tekscie, co utrudnia czytanie, ale wartosc merytoryczna wysoka.

Brak druku do PDF
Środa 22 Luty 2006 9:27:25 pm - angel2953

Dlaczego jest brak możliwości pobrania tego artykułu jako pliku PDF ? Lub jeśli ów link istnieje (ja go jakoś nie potrafię zlokalizować) dlaczego jest tak słobo widoczny ?

prosty temat
Sobota 28 Styczeń 2006 6:00:51 pm - emp

po prostu zrob sobie swoje klasy i chierarchie klas i masz szkielety aplikacji i do tego bardzo modularne

Profesjonalizm
Niedziela 15 Styczeń 2006 12:22:17 pm - aztech <scrabblewroclaw_at_op.pl>

Cieszę się, że uwagi jakie zgłosiłem co do wyglądu listingów oraz ich podlinkowania zostały zauważone i szybko wprowadzone. To świadczy o profesjonalnym podejściu osób tworzacych ten wortal.
Brawo!

Brak danych :)
Piątek 13 Styczeń 2006 10:32:09 pm - ..:: pingu ::.. <pingu_at_interia.pl>

W PDF'ie ten artykuł wyglada duzo lepiej :P

Szkoda ze czasem trzeba przejsc na nastepna strone aby zobaczyc listing :(

Mentax.pl    NQ.pl- serwery z dodatkiem świętego spokoju...   
O nas | Kontakt | Mapa serwisu
Copyright (c) 2003-2017 php.pl    Wszystkie prawa zastrzeżone    Powered by eZ publish Content Management System eZ publish Content Management System