Eloquent ORM

xvital
napísal @xvital (270), pred 2 mesiacmi

Eloquent (plynulý, ladný, dokonalý) je ORM, ktoré je súčasťou Laravelu. Tak ako hovorí samotný názov, ide o veľmi príjemné a prirodzené rozhranie pre prácu s objektami a interakcie s databázou. V jednoduchých aplikáciach tak priamo s SQL nemusíte prísť vôbec do kontaktu.

Dnes sa bližšie pozrieme na

  1. vytváranie objektov
  2. ukladanie objektov do databázy
  3. vzťahy medzi modelmi
  4. základné operácie na objektoch a ich vzťahoch

Prerekvizity

V tomto bode by ste mali mať nainštalovaný Laravel a nakonfigurovaný prístup k databáze. Pre účely ukážky práce s modelmi a vzťahmi poslúži ako príklad jednoduchá aplikácia - blog, ktorá bude obsahovať dva modely: User a Post.

Eloquent model

Je na vás aký workflow si zvolíte, prvým krokom však väčšinou bude vytvorenie modelov. Výhodou je, že Laravel v základe obsahuje jednoduchý model User a kompletnú implementáciu autentifikácie. Keďže aplikácia už model User obsahuje, vytvárať budeme už len model Post:

php artisan make:model Post -m

Použil som prepínač -m, aby mi artisan pripravil migráciu pre tabuľku posts.

Model created successfully.
Created Migration: 2019_01_29_085958_create_posts_table

V migrácii pripravíme požadovanú štruktúru tabuľky

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreatePostsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->increments('id');
            $table->timestamps();

            /* Nazov clanku */
            $table->string('subject');
            /* Obsah clanku */
            $table->text('body');

            /**
             * Tabulka users je v dobe vykonavania tejto migracie uz vytvorena
             * mozeme na nu odkazovat v cudzom kluci
             */
            $table->integer('user_id')->unsigned();
            $table->foreign('user_id')->references('id')->on('users');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('posts');
    }
}

V tomto bode máme vytvorené tabuľky a môžeme sa pozrieť na model User, ktorý zatiaľ neobsahuje žiadne vzťahy, len niekoľko vlastných premenných, ktoré definujú prístup a viditeľnosť k atribútom modelu (o týchto premenných sa dozviete ďalej v článku).

Vzťah s modelom Post definujeme ako 1:N (1 užívateľ môže vytvoriť N článkov). V modeli User teda implementujeme metódu posts ako vzťah hasMany, nasledovne:

public function posts()
    {
        return $this->hasMany('App\Post');
    }

Model Post obsahuje zatiaľ prázdnu triedu Post, ktorú nám vygeneroval artisan. Sem pridáme vzťah s modelom User. Ide o opačnú stranu vzťahu 1:N, použijeme metódu belongsTo.

public function user() 
    {
        return $this->belongsTo('App\User');
    }

Vytváranie nových objektov

Na vytvorenie objektov môžeme použiť explicitný prístup: vytvoriť model, nastaviť atribúty na požadované hodnoty a nakoniec model uložiť (perzistovať ho do databázy).

$post = new Post;

$post->subject = 'Hello World!';
$post->body = 'How are you?';

$post->save();

Eloquent však na vytváranie objektov poskytuje jedoduchšiu metódu create, vďaka ktorej vytvoríte nový objekt rýchlejšie, predaním poľa s parametrami

Post::create([
      'subject' = 'Hello World!',
      'body' = 'How are you?'
]);

Používanie vzťahov medzi modelmi

Jedna z predností Active Record je práve jednoduchosť používania vzťahov. Ak chceme získať autora článku a máme k dispozícii článok

$author = $post->user;

Ak chceme zoznam článkov, ktoré napísal daný autor

$posts = $user->posts;

Tak jednoduchý môže byť prístup ku vzťahovým modelom.

Niekedy však potrebujete tento výber obmedziť/filtrovať. Volanie metódy vzťahu vracia Query Builder objekt (v tomto prípade HasMany), ktorý môžete zreťaziť s ďalšími metódami Query Buildera a samotný SQL dotaz vykonať až na konci volaním get(). Vtedy dôjde k spojeniu s databázou a vykonaniu samotnému dotazu.

// volanie vztahu a filtrovanie pouzitim where
dd($user->posts()->where('subject', 'like', '%hello%')->latest());

// vysledkom je objekt typu HasMany
HasMany {#209 ▼
  #foreignKey: "posts.user_id"
  #localKey: "id"
  #query: Builder {#206 ▶}
  #parent: User {#212 ▶}
  #related: Post {#201 ▶}
}

// to iste co vyssie, ale ukoncene volanim metody get()
dd($user->posts()->where('subject', 'like', '%hello%')->latest()->get());

// vysledkom je zoradena kolekcia objektov, ktore zodpovedaju splnaju klauzulu where
Collection {#213 ▼
  #items: array:3 [▼
    0 => Post {#214 ▶}
    1 => Post {#218 ▶}
    2 => Post {#219 ▶}
  ]
}

Eloquent obsahuje implementáciu rôznych vzťahov, ktoré budete pri vývoji aplikácií potrebovať

  • one to one
  • one to many
  • many to many
  • has many through
  • polymorfné vzťahy

Kompletný prehľad, detaily a použitie nájdete v dokumentácii.

Prednačítanie vzťahov (Eager loading)

V úvodných, jednoduchých príkladoch som využil prístup ku vzťahovým modelom cez dynamické atribúty. Veľmi praktické a jednoduché. Je však potrebné uvedomiť si, ako to celé funguje. Ak pristupujeme ku vzťahu ako k dynamickému atribútu objektu na ktorom vzťah voláme, SQL dotaz sa vykoná v danej chvíli. Ak použijete vzťah ako dynamický atribút druhýkrát, opäť sa vykoná rovnaký SQL dotaz. V určitých situáciach teda môžete zbytočne pristupovať do databázy niekoľkokrát a vyberať pri tom rovnaké dáta. Laravel preto ponúka možnosť tzv. eager loadingu, čo znamená že vzťah, resp. vzdialený objekt sa prednačíta a stane sa súčasťou vybraného objektu. Pre prístup k dátam vzdialeného objektu už nebude potrebné dotazovať sa do databázy.

Fillable, guarded a hidden atribúty modelov

V triede modelu môžete obmedziť hromadné vyplňovanie atribútov. Slúžia na to špeciálne premenné $fillable a $guarded. Guarded – je zoznam chránených atribútov, ktoré bude Laravel za vás strážiť, aby sa nevypĺňali hromadne (napríklad pri použití metódy create). Všetky atribúty, ktoré nebudú definované v tomto zozname, bude možné vypĺňat hromadne. Fillable – je má inverznú funkciu ako guarded – atribúty vymenované v zozname sa budú dať hromadne vypĺňať, u ostatných to možné nebude. Zoznamy definujete ako pole atribútov. Používajte podľa potreby buď guarded, alebo fillable. Ak chcete, aby niektoré atribúty modelu neboli obsiahnuté v dátach, ktoré vám Eloquent vráti, definujte ich v premennej $hidden. Podobne ako u vyššie uvedených, definujete skryté atribúty ako pole atribútov. Vhodné hlavne pre atribúty, ktoré môžu predstavovať bezpečnostné riziko.

Ako vždy, detailné informácie a hlavne mnoho ďalších funkcií a možností, ktoré ponúka Eloquent, nájdete v dokumentácii pre ORM Eloquent.

Ešte nie si členom CZ/SK Laravel komunity?

To možeš ľahko zmeniť. Registrácia je zdarma a ako registrovaný člen získaš množstvo výhod. Prečítaj si prečo by si mal byť členom.

Prihlásiť sa Zaregistrovať

Mohlo by Ťa zaujímať: