Jakiś czas temu Renholder opisał jak rozszerzyć klasę CI_MODEL. W artykule pojawił się odnośnik, do dwóch gotowych projektów tego typu. Jeden z nich to klasa o nazwię codeigniter-base-model autorstwa niejakiego Jamie Rumbelow’a.
Pytanie jest proste – po co w ogóle się za to zabierać? Prawda jest taka, że CI jest dosyć „biedny” w porównaniu do innych frameworków. Nie ma porządnego ORM, nie ma automatycznych modeli – nie ma nic co pozwala na faktycznie szybkie prototypowanie aplikacji. Oczywiście każdy zaraz powie – przecież można napisać sobie samemu! oczywiście – zgadzam się. Przychodzi to z wiekiem – DRY. Jeżeli mogę zaoszczędzić 10 linii kodu, bo ktoś napisał je za mnie. Dlaczego nie. Do dzieła.
Ok. Instalacja biblioteki jest bajecznie prosta. Wystarczy pobrać ją z GitHub’a. Wgrać plik MY_Model.php do folderu application/core i… gotowe. Teraz utworzymy sobie model, który wykorzystuje tą bibliotekę.
Tworzymy pliki post_model.php w folderze application/models. Do środka wkładamy jedna linijkę kodu:
<?php class Post_model extends MY_Model { }
Tyle. Teraz w kontrolerze ładujemy nasz model przez
$this->load->model('post_model', 'post');
I już na tym etapie uzyskujemy dostęp do szeregu metod. Jeżeli nie zdefiniujemy własnej tabeli, model będzie spodziewał się tabeli posts w bazie danych. Jeżeli chcemy zdefinować własną możemy to zrobić tak:
class Post_model extends MY_Model
{
public $_table = 'blogposts';
}
Ok. Wracając do naszej biblioteki, jak ułatwia nam ona pracę. Na wiele sposobów – spróbujmy coś wyciągnać z bazy danych:
$this->post->get_all();
$this->post->get(1);
$this->post->get_by('title', 'Pigs CAN Fly!');
$this->post->get_many_by('status', 'open');
Proste prawda? Nie trzeba chyba tłumaczyć jaka jest idea poszczególnych opcji. Pobieramy wszystko, dany rekord wg klucza głównego, wyciągam poprzez kolumnę tytuł a finalnie wiele wiersze wg. kolumny status. Oczywiście można przekazywać też całe tablice parametrów:
$this->post->get_by(array('id' => 1, 'status' => 'open'));
Teraz dodamy coś do bazy
$this->post->insert(array(
'status' => 'open',
'title' => "I'm too sexy for my shirt"
));
I zaktualizujemy
$this->post->update(1, array( 'status' => 'closed' ));
Usuwanie rekordów też nie jest bardzo skomplikowane:
$this->post->delete(1);
Jednak moja ulubiona funkcja tej biblioteki, to obserwatory:
$before_create $after_create $before_update $after_update $before_get $after_get $before_delete $after_delete
Brzmi znajomo? Tak – dzięki nim możesz zdefiniować dodatkowe akcje po wykonaniu danej operacji na wybranym rekordzie. Czyli „after_delete” – można uruchomić funkcję czyszczącą inne tabele, logi, albo cokolwiek innego. Ewentualnie przeformatować dane przed dodaniem to tabeli korzystając z „before_create”. Użycie jest bardzo proste:
class Book_model extends MY_Model
{
public $before_create = array( 'timestamps' );
protected function timestamps($book)
{
$book['created_at'] = $book['updated_at'] = date('Y-m-d H:i:s');
return $book;
}
}
Tyle. Zachęcam do wyprobówania tej klasy przy najbliższym projekcie. Więcej informacji codeigniter-base-model
Warto zaznaczyć, że walidacja działa tutaj na trochę innych zasadach niż zazwyczaj. Jest przeprowadzana dopiero w momencie dodawania lub modyfikacji danych w tabeli.
CodeIgniter rzeczywiście nie ma jakoś szczęścia do dedykowanych systemów ORM – DataMapper ORM produkuje często trochę dziwne zapytania (szczególnie przy późnym wiązaniu), a Gas ORM obsługuje jedynie proste zapytania (w sumie ok, ale łączenia czasami jednak się przydają).