Laravel Eloquent: najważniejsze funkcje ORM-a w Laravelu 8

Laravel Eloquent: najważniejsze funkcje ORM-a w Laravelu 8
Eloquent, dostarczany razem ze znanym frameworkiem PHP Laravel, daje elegancki i bardzo wydajny sposób rozmawiania z bazą danych. Strony internetowe robią się coraz bardziej złożone przez kolejne personalizacje, a deweloperzy zostają z równie złożonymi bazami. Laravel Eloquent radykalnie upraszcza obsługę tego wszystkiego. Zostawia swobodę pisania kodu dobrze sformatowanego, czytelnego, trwałego i dobrze udokumentowanego. Ten zestaw możliwości to jeden z powodów popularności Laravela.W tym artykule omawiam najważniejsze funkcje ORM-a Eloquent.

Czym jest Eloquent ORM?

Eloquent ORM jest dostarczany razem z frameworkiem Laravel, żeby dać prosty i bezproblemowy sposób pracy z bazą danych. Funkcje, które przyniosły mu rozgłos, to soft delete, timestampy, implementacja Active Record, obsługa wielu baz danych, eager loading, obserwatory modeli, zdarzenia modeli i wiele innych. Relacje Eloquenta to zwykłe metody klas modeli. Zdefiniowane jako metody, stają się potężnymi konstruktorami zapytań: można na nich łańcuchowo wywoływać kolejne metody i budować naprawdę mocne zapytania.

Jak działa Eloquent ORM?

Eloquent ORM zasłynął implementacją wzorca Active Record do pracy z bazami danych. Active Record to wzorzec architektoniczny, w którym każdy model architektury MVC odpowiada jednej tabeli w bazie. Dzięki Eloquentowi łatwo tworzysz powiązane dane i pracujesz z nimi obiektowo. Ręczne pisanie zapytań SQL jest żmudne i pochłania mnóstwo czasu, a Laravel Eloquent pozwala wykonywać typowe operacje na bazie bez długich zapytań. Modele bardzo ułatwiły wstawianie, aktualizowanie, usuwanie i synchronizowanie wielu baz danych. Wystarczy zdefiniować tabele i relacje między nimi, i po robocie.

Pierwsze kroki z Eloquentem

Laravel ma wbudowany interfejs wiersza poleceń o nazwie Artisan Console. Napędza go komponent Console z Symfony, dzięki czemu wygodnie korzysta się z linii poleceń w trakcie budowania aplikacji.

Zanim pójdziemy dalej, skonfiguruj połączenie z bazą danych w pliku config/database.php.

Zanim zaczniesz korzystać z modelu Eloquent, sprawdź, czy masz zainstalowanego Laravela. Jeśli nie, pobierzesz go z getcomposer.org

Żeby zobaczyć listę poleceń dostępnych w Artisanie, uruchom:

bash
php artisan list

Na ekranie pojawią się wszystkie polecenia z krótkim opisem. Jeśli potrzebujesz pomocy do któregoś z nich, wpisz je poprzedzone słowem „help”. Na przykład:

bash
php artisan help migrate

Tworzenie modeli Eloquent

Zanim zrobisz cokolwiek innego, potrzebujesz modelu dla swojej tabeli. Modele przydają się przy seedowaniu, fabrykach i całej reszcie. To model rozmawia z bazą danych: pozwala odpytywać tabele i wypełniać je danymi. Modele trzyma się zwykle w App\Models i chodzi wyłącznie o porządek w kodzie. My też wolimy tę konwencję, ale wybór należy do ciebie, jedyny warunek to autoloading klasy zgodny z plikiem composer.json. Każdy model Eloquent rozszerza klasę Illuminate\Database\Eloquent\Model. Podstawowe polecenie do tworzenia modeli to polecenie Artisana `make:model` :

bash
php artisan make: model Student

Podstawowa składnia definicji modelu wygląda tak:

php
class User extends Model {}

Migrację można wygenerować razem z modelem, dopisując do poprzedniego polecenia `-m` albo `–migration`.

bash
php artisan make:model Student--migration
php artisan make:model Flight -m

Seedery, fabryki, kontrolery i inne klasy generuje się, przekazując odpowiednie opcje do polecenia `make:model` . Kilka przykładów:

bash
php artisan make:model Flight --factory
php artisan make:model Flight -f

php artisan make:model Flight --seed
php artisan make:model Flight -s

php artisan make:model Flight --controller
php artisan make:model Flight -c

Te opcje można też łączyć, żeby utworzyć kilka klas naraz.

bash
php artisan make:model Flight -mfsc

Kilka podstawowych konwencji modeli, o których warto pamiętać:

  • Nazwa tabeli: zgodnie z konwencją nazwy tabel zapisuje się małymi literami i w liczbie mnogiej, w każdej bazie danych. Jeśli model nazywa się Student, tabela powinna nazywać się students. Kiedy nazwa modelu składa się z kilku słów, rozdziel je podkreśleniem.
  • Klucz główny: Eloquent zakłada, że kluczem głównym jest atrybut id. Możesz to nadpisać właściwością `$primaryKey`.
  • Timestampy: domyślnie `created_at` i `updated_at` są obsługiwane automatycznie przez Eloquenta. Jeśli wolisz zająć się nimi sam, ustaw `$timestamps` na false. A żeby zmienić format daty i godziny, użyj w modelu właściwości `$dateFormat`.

Aktualizowanie i usuwanie rekordów

Aktualizowanie

Żeby zaktualizować model, pobierz go, zmień wybrany atrybut i wywołaj metodę save. Kolumna `updated_at` aktualizuje się sama, więc nie musisz jej ruszać ręcznie.

php
$student = Student::find(1);

$student->email = ‘xyz@example.com';

$student>save();

Aktualizacje masowe da się wykonać na wszystkich modelach pasujących do danego zapytania.

Usuwanie istniejącego modelu

Żeby usunąć model, wystarczy wywołać metodę delete:

php
$student = Student::find(1);

$student>delete();

Usuwanie po kluczu:

php
Student::destroy(1);

Student::destroy([1, 2, 3]);

Student::destroy(1, 2, 3);

Usuwać można również na podstawie zapytania.

php
$affectedRows = Student::where('votes', '>', 100)->delete();

Powiązane modele

W każdej bazie danych mogą istnieć powiązane modele. Kiedy dwa modele albo więcej zależą od siebie wartościami, mówimy o modelach powiązanych. Na przykład dodając nowy komentarz do wpisu, zamiast ręcznie ustawiać post_id możesz zapisać komentarz prosto z modelu nadrzędnego

php
$comment = new Comment(['message' => 'A new comment.']);

$post = Post::find(1);

$comment = $post->comments()->save($comment);

Wiązanie modeli

Modele aktualizuje się też metodą associate, która ustawia na modelu klucz obcy. W ten sposób da się wiązać modele w kilku relacjach naraz.

Zdarzenia modelu

Za każdym razem, gdy chcesz wpiąć się w etapy cyklu życia modelu, zapis, aktualizację czy usunięcie, wywoływane jest zdarzenie modelu. Dostępne zdarzenia to saving, saved, deleting, deleted, updating, updated, restoring i restored. Wstawienie nowego rekordu uruchamia zdarzenie creating/created, a rekord, który już istnieje, uruchamia updating/updated.

Anulowanie zapisu ze zdarzenia

Jeśli zdarzenie zwróci false, akcja zostanie anulowana. Zadziała to z dowolnym zdarzeniem: deleting, updating, creating i tak dalej.

php
Student::creating(function($student)
{
    if ( ! $student>isValid()) return false;
});

Jak rejestrować listenery zdarzeń

Jak w każdym języku, zdarzenie potrzebuje service providera, żeby dało się je zarejestrować, i z listenerami jest tak samo. Laravel dostarcza EventServiceProvider i to tam rejestruje się powiązania zdarzeń modeli.

Na przykład:

php
public function boot(DispatcherContract $events)
{
    parent::boot($events);

Student::creating(function($student)
    {
        //
    });
}

Obserwatory modelu

Obserwatory modeli pomagają obsłużyć zdarzenia modeli. Klasa obserwatora może mieć po jednej metodzie na każde zdarzenie.

php
class StudentObserver {

public function saving($model)
    {
        //
    }

public function saved($model)
    {
        //
    }

}

Obserwator rejestruje się także metodą observe

php
User::observe(new UserObserver);

Generowanie adresów URL modelu

Adresy URL modelu dają adres pojedynczego rekordu: wystarczy przekazać model do helpera route albo action. Kiedy model trafia do route lub action, w URI wstawiany jest jego klucz główny.

php
Route::get('student/{student}', 'StudentController@show');

action('StudentController@show', [$student]);

Tutaj w adresie znajdzie się id studenta. Jeśli w wygenerowanym adresie ma się pojawić inna właściwość, nadpisz metodę getRouteKey w swoim modelu.

php
public function getRouteKey()
{
    return $this->slug;
}

Więcej o funkcjach Laravel Eloquent

Konwersja na tablice i JSON

Kiedy budujesz API, odpowiedź prawie zawsze jest w JSON-ie, więc modele i ich relacje trzeba zamienić na JSON albo tablicę. Laravel Eloquent obsługuje i to. Żeby zamienić model wraz z relacjami na tablicę, użyj metody toArray().

php
$student = Student::with('roles')->first();

return $student->toArray();

Żeby zamienić na tablicę całą kolekcję modeli, można użyć takich metod:

php
return Student::find(1)->toJson();

Zobaczmy teraz, jak zwrócić model z trasy. Model rzutowany na łańcuch znaków zamienia się w JSON, więc obiekty Eloquenta możesz zwracać prosto z tras.

php
Route::get('student', function()
{
    return Student::all();
});

Część wartości, jak `personal_id` czy hasło, trzeba ukryć. Dodaj w tym celu do modelu `$hidden`.

Rzutowanie atrybutów

Jeśli chcesz zmienić typ danych atrybutu, jedną z opcji jest napisanie mutatora dla każdego z nich, co zajmuje czas i sprzyja błędom. Druga opcja to rzutowanie danego atrybutu: dopisz go do właściwości casts swojego modelu. Pozostałe akceptowane typy rzutowania to integer, float, double, real, object, string, array.

Oto przykład.

php
protected $casts = [
    'is_student' => 'boolean',
];

W tym przykładzie, mimo że is_student jest przechowywana z innym typem danych, przy odczycie zawsze dostaniesz boolean.

Rzutowanie na tablicę bardzo się przydaje przy kolumnie zawierającej serializowany JSON. Serializowany JSON to po prostu obiekt zakodowany jako łańcuch znaków. Jeśli któraś z kolumn go trzyma, rzutowanie na tablicę zamieni ją automatycznie w tablicę PHP, gdy tylko odczytasz ją z modelu Eloquent.

php
protected $casts = [
    'options' => 'array',
];

Mutatory dat

Carbon to międzynarodowe rozszerzenie klasy DateTime z PHP. Eloquent zamienia created_at i updated_at na instancje Carbona, które rozszerzają klasę DateTime i dokładają kilka przydatnych metod. Jeśli nie chcesz automatycznej mutacji, dostosowanie jest proste: nadpisz w swojej klasie metodę getDates . Żeby wyłączyć mutację dat całkowicie, zwróć pustą tablicę z metody `getDates` . Oto przykład:

php
public function getDates()
{
    return ['created_at'];
}

Kiedy kolumna jest traktowana jak data, jej wartością mogą być cztery rzeczy: timestamp UNIX, łańcuch z datą (Y-m-d), łańcuch z datą i godziną albo instancja DateTime/Carbon.

Akcesory i mutatory

Podobnie jak odczyt i zapis wartości w dowolnym języku, akcesory i mutatory pozwalają formatować atrybuty Eloquenta, zanim zostaną odczytane z instancji modelu albo do niej zapisane. Różnica jest taka, że akcesory służą do odczytu danych, a mutatory odpowiadają za ich zmianę.

Żeby zdefiniować akcesor, zadeklaruj w modelu metodę `getFooAttribute` , jej nazwa musi być zapisana w camelCase, nawet jeśli kolumna jest zapisana małymi literami.

php
class User extends Model {

public function getFirstNameAttribute($value)
    {
        return ucfirst($value);
    }

}

Mutator definiuje się tak samo: użyj `setFooAttribute` i tak, camelCase obowiązuje również tutaj.

php
class User extends Model {

public function setFirstNameAttribute($value)
    {
        $this->attributes['first_name'] = strtolower($value);
    }

}

Soft delete

Soft delete nie usuwa wiersza z bazy, tylko zapisuje osobny timestamp. Na rekordzie wypełniana jest kolumna `deleted_at` . Soft delete włączasz w modelu, dodając do niego trait SoftDeletes.

php
use Illuminate\Database\Eloquent\SoftDeletes;

class User extends Model {

use SoftDeletes;

protected $dates = ['deleted_at'];

}

softDeletes() dodaje w migracji kolumnę deleted_at. Migracja to nic innego niż zarządzanie bazą danych w PHP zamiast w SQL-u.

php
$table->softDeletes();

Czasem chcesz, żeby rekordy usunięte miękko pojawiły się w wynikach zapytania. Wystarczy dodać withTrashed() do zapytania.

Jeśli w wynikach mają się znaleźć wyłącznie modele usunięte miękko, użyj onlyTrashed() w zapytaniu.

php
$student = Student::onlyTrashed()->where('account_id', 1)->get();

Po tych wszystkich operacjach, jeśli chcesz przywrócić modele usunięte miękko do aktywnego użycia, wywołaj metodę restore.

php
$student->restore();

restore() można też wywołać bezpośrednio w zapytaniu.

php
Student::withTrashed()->where('account_id', 1)->restore();

Teraz, po miękkim usunięciu, jeśli chcesz skasować model z bazy na dobre, użyj forceDelete() na modelu.

php
$student->posts()->forceDelete();

Żeby sprawdzić, czy model został usunięty, sięgnij po metodę trashed().

php
if ($student->trashed())
{
    //Do zrobienia
}

Podsumowanie

Laravel to jeden z najbardziej znanych frameworków PHP, a Laravel Eloquent daje bardzo prosty sposób rozmawiania z bazami danych. W tym artykule omówiłem część ważnych funkcji Eloquenta. Jest ich znacznie więcej i poczytasz o nich tutaj. Wejdź na ten link i sprawdź wszystko, co potrafi Laravel Eloquent.


LaravelPHP

Damien Flandrin Web developer od 2010 roku, twórca Gekkode i Email Impact. Każdy artykuł jest sprawdzany na prawdziwym projekcie przed publikacją. Kontakt
Newsletter

Nowe testy, poradniki i projekty — e-mailem.

Powtarzalne testy, wersjonowany kod, datowane wyniki. Nigdy spamu.