Budowa prostego MVC w PHP (>5.3), cz. 2 – warstwa Modelu
Killavus dnia Marzec 23, 2011
W ostatnim artykule przybliżyłem trochę na czym polega model MVC, dlaczego jest przydatny i jest pożądanym wzorcem projektowym w wielu zastosowaniach. Django, czy Ruby on Rails używają tego modelu z bardzo dobrym skutkiem – znacząco zmniejsza to czas projektowania aplikacji sieciowej. Pozwala to np. stworzyć bloga w 15 minut, wraz z pełnym panelem administracyjnym właśnie w RoR.
Dzisiaj zajmiemy się warstwą Modelu – niewątpliwie najbardziej skomplikowaną częścią tego modelu. Efektywne zaimplementowanie tej warstwy to tak naprawdę najważniejsza część – reszta jest dość prosta do napisania i tam raczej cudów nie ma. Stworzymy klasę abstrakcyjną, która pozwoli na rozszerzanie modeli w nieskończoność, korzystając z tego samego interfejsu. W następnej części zaimplementujemy także klasę potomną od naszego abstrakcyjnego modelu, która będzie pobierała dane z baz danych. Wykorzystamy w tym celu PDO, co będzie doskonałym ćwiczeniem w programowaniu z użyciem tego zestawu klas.
Nasz Model, z racji tego, że ma być prosty, nie będzie uwzględniał takich rzeczy jak połączenia między danymi, czy też szukanie po warunkach – przyjemność implementacji tych funkcji pozostawiam czytelnikowi. W razie problemów chętnie posłużę radą.
Własności naszych danych:
Aby efektywnie i prosto zaimplementować nasz Model, dane będą spełniały pewne właśności, które są dość powszechne i nie będą specjalnie zaskakujące. Prawdę mówiąc, wszystkie te własności spełnia każda dobrze stworzona baza danych. Przede wszystkim, każdy zestaw danych będzie jednoznacznie reprezentowany przez identyfikator liczbowy (ID). Jest to ważne, ponieważ musimy mieć jakąś szansę na dostanie się do naszych danych i musi to być szansa niezależna od ich typu. ID jest najprostszym sposobem. Drugą własnością będzie to, że struktura danych będzie znana przed jakąkolwiek manipulacją nimi. Jest to dość oczywiste, gdyż musimy wiedzieć tak naprawdę co pobieramy. Teoretycznie możliwe jest także odrzucenie tej własności – w przypadku pobierania np. z pliku tekstowego w formacie:
id = 2 foo = 'bar' p = 12 x = 19.282
Własność nie musi być spełniona, gdyż mamy podane etykiety danych. My jednak założymy, że strukturę danych znamy – ułatwi nam to w przyszłości np. używanie naszego modelu z bazą danych.
Co chcemy zrobić z danymi?:
Pytanie wydaje się trywialne, ale warto się nad nim zastanowić. To, co nasuwa się samo to oczywiście możliwość pobierania danych z naszego źródła. Po to w końcu tworzymy nasz model, prawda? Ale nie tylko. Przydałaby się także możliwość manipulacji danymi już pobranymi, a także zapis zmanipulowanych danych spowrotem do źródła danych, tworzenie nowych danych oraz usuwanie danych ze źródła. To wszystko będzie realizowane właśnie przez nas model. Warto mieć tą wiedzę jeszcze przed pisaniem czegokolwiek, pozwoli to nam na głębsze przemyślenie struktury kodu. Ogólnie, przed napisaniem czegokolwiek polecam najpierw rozplanować sobie program na kartce – piszemy wtedy kod zdecydowanie lepszy, bardziej przemyślany i przez to krótszy.
Abstrakcyjny model klasy:
Skoro już wiemy, czego pragniemy od naszej klasy, możemy zacząć ją powoli tworzyć. Wiemy, że każdy rekord jest reprezentowany przez ID. Skoro chcemy ładować dane, stwórzmy metodę load, przyjmując nasz ID jako argument. I tak, kod:
$model->load(1);
Załaduje nam rekord o ID równym 1 ze źródła danych. Nasze dane będziemy przechowywać w tablicy $data. Pozwoli nam to na prostą implementację manipulowania danymi (wprost) oraz pobierania ich. Aby korzystać z wygodnej składni w stylu:
echo $model->foo; $model->foo = 'bar';
Skorzystamy z magicznych metod PHP: funkcji __get($key) oraz __set($key,$data). Korzystając z tego, że mamy dane w tablicy, implementacja tych metod jest trywialna:
public function __get($key) { if( !isSet($this->data[$key]) ) return NULL; return $this->data[$key]; } public function __set($key,$value) { $this->data[$key] = $value; }
Oczywiście, nie uwzględniamy tutaj np. walidacji danych. Musimy to uwzględnić sami, nim jeszcze przypiszemy dane do modelu. Oczywiście, są też inne metody rozwiązania tego problemu, nie opiszę ich jednak w tym artykule z dwóch powodów – po pierwsze, model musi pozostać prosty, a po drugie, nie chce mi się.
Oczywiście, musimy mieć także strukturę daną w momencie tworzenia obiektu. Stwórzmy więc statyczną tablicę $structure, przechowującą naszą strukturę danych oraz structure(), metodę uruchamianą w konstruktorze, która będzie zwracała naszą strukturę danych do tablicy. Aby zapewnić także możliwość wstawiania nowych rekordów do źródła danych, stwórzmy także wartość logiczną $virtual. Dane będą wirtualne, gdy nie będą istniały w źródle danych – pojawią się tam dopiero, gdy je zapiszemy. Praktyczna implementacja takiego konstruktora może wyglądać następująco:
public function __construct( $id = NULL ) { istatic::$structure = static::structure(); $this->virtual = is_null($id)? TRUE : FALSE; if( !$this->virtual ) $this->load($id); }
Jak widać, w momencie gdy tworzymy model, ładujemy statyczną metodę structure(), która zwraca nam tą strukturę. To bardzo praktyczne – w dzieciach tej klasy wystarczy jedynie nadpisać tą metodę.
Podsumowanie:
Reszta metod jest metodami abstakcyjnymi i nie będziemy się nimi zajmować. Poniżej zamieszczam gotową klasę, która będzie stanowić interfejs naszych modeli. Jak widać, nie jest to takie trudne. Jakiekolwiek funkcje, które są zależne od typu danych powinny być nadpisywane przez klasy potomne.
Przykładowa klasa AbstractModel.php:
<?php abstract class AbstractModel { protected static $structure; protected $data, $virtual; public function __get($key) { if( !isSet($this->data[$key]) ) return NULL; return $this->data[$key]; } public function __set($key,$value) { $this->data[$key] = $value; } public function __construct( $id = NULL ) { if( !isSet(static::$structure) ) static::$structure = static::structure(); $this->virtual = is_null($id)? TRUE : FALSE; if( !$this->virtual ) $this->load($id); } abstract public function save( $id = NULL ); abstract public function delete(); abstract public function load( $id ); abstract static public function structure(); } ?>
To wszystko na dziś. Mam nadzieję, że poradnik będzie przydatny!
2 komentarzy
[...] Read more from the original source: PHP Blog on:Budowa prostego MVC w PHP (>5.3), cz. 2 – warstwa Modelu [...]
autor: PHP Blog on:Budowa prostego MVC w PHP (>5.3), cz. 2 – warstwa Modelu | MiloRiano: Computers news, tips, guides... data: 23 marca 2011, 20:52. #
page rank check seo workshop backlink url buy backlinks
autor: get backlinks data: 26 września 2011, 2:39. #