Devloger

Query Scopes - Czym są? Jak ich używać?

Query Scopes | Laravel Eloquent

Eloquent - Query Scopes

Jeśli nurtują cię takie pytania i nie wiesz czym są query scopes w systemie ORM Eloquent to w tym artykule wszystko ci rozjaśnię Emotikon uśmiechniętej buźki. Jest to również kwestia nad którą często zastanawiają się osoby poznające dopiero system Eloquent.

Zatem cóż to takiego?

Ano jest to najprościej mówiąc sposób, dzięki któremu możemy nadać pewne ograniczenia/restrykcje co do naszych zapytań związanych z konkretnym modelem. Wyobraźmy sobie na przykład model użytkownika. I chcemy nadać restrykcje pozwalające operować tylko na użytkownikach aktywnych - z wykorzystaniem Query Scopes możemy tego dokonać Emotikon uśmiechniętej buźki!

Również takim przykładem już strikte Laravelowym może być sposób działania soft deletes (miękkich usunięć rekordów z bazy danych). Działa to w ten sposób że rekordy usunięte "miękko" zostają pominięte w wynikach naszych zapytań – lecz wciąż istnieją Emotikon uśmiechniętej buźki.

Jakie mamy rodzaje Query Scopes?

Query Scopes dzielimy na globalne i lokalne. Globalne odnoszą się do wszystkich (prawie) zapytań w naszym modelu natomiast lokalne są bardziej re-używalne i na żądanie.

Czy restrykcje nakładamy na absolutnie wszystkie zapytania?

Nie do końca. Otóż możemy nałożyć je globalnie, wówczas będą oddziaływać na wszystkie zapytania w naszej aplikacji - z wyłączeniem tych, w których osobiście każemy wykonać zapytanie z pomięciem danych restrykcji (mamy taką możliwość).

Możemy również stworzyć je lokalnie, wówczas jesteśmy w stanie wykorzystać je wedle uznania. W przypadku globalnych musielibyśmy je wyłączać. Natomiast w lokalnych je włączamy.

Jak napisać Global Scope?

Bardzo prosto, wystarczy stworzyć klasę która implementuje interfejs Illuminate\Database\Eloquent\Scope, który z kolei obliguje nas do implementacji w klasie tylko jednej metody - apply. W tej metodzie możemy dodawać wszelkie restrykcje (związane z tym Query Scope) które później zaaplikujemy do naszego modelu. Metoda ta akceptuje instancję buildera oraz modelu.

<?php

namespace App\Scopes;

use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;

class AgeScope implements Scope
{
    /**
     * Apply the scope to a given Eloquent query builder.
     *
     * @param  \Illuminate\Database\Eloquent\Builder  $builder
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @return void
     */
    public function apply(Builder $builder, Model $model)
    {
        $builder->where('age', '>', 200);
    }
}

Jak przypisać Global Scope do modelu?

Jeszcze prościej, wystarczy nadpisać statyczną metodę boot z klasy bazowej w naszym modelu w którym przypiszemy go za pomocą statycznej metody addGlobalScope podając jako argument nową instancję wcześniej utworzonej klasy Scope.

Czy za każdym razem muszę tworzyć nową klasę Scope?

Na szczęście nie, jeśli masz prostą formułę dla twojego Scope, wówczas możesz dokonać tego za pomocą funkcji anonimowej ale również znajdującej się w metodzie boot, którą musisz nadpisać. Tutaj przyjmuje już tylko jako argument instancję buildera.

protected static function boot()
{
    parent::boot();

    static::addGlobalScope(new AgeScope);
}

Jak pozbyć się globalnego Scope z zapytań?

Wystarczy, że przy tworzeniu zapytania na modelu posłużysz się metodą withoutGlobalScope podając do niej jako argument klasę lub klasy Scope których chcesz się pozbyć Emotikon uśmiechniętej buźki.

A co z lokalnymi Query Scope?

Jak już mówiłem, są to Query Scope które możemy użyć kiedy tylko będziemy chcieli. Są one re-używalne. Piszemy je raz i możemy wykorzystać w wielu miejscach w naszym kodzie w odniesieniu do danego modelu. Przypuśćmy że bardzo często wyciągasz z bazy użytkowników którzy są aktywni. Wówczas w wielu miejscach powtarzasz ciągle tę samą formułę where. Zamiast tego możesz napisać prosty Query Scope i używać go gdzie tylko chcesz ułatwiając sobie pracę Emotikon uśmiechniętej buźki.

Jak napisać lokalny Query Scope?

Jeszcze prościej niż globalny, wystarczy napisać nową publiczną metodę w danym modelu np. Active ale poprzedzoną prefixem "scope". Metoda ta akceptuje instancję buildera.

public function scopeActive($query)
{
    return $query->where('active', 1);
}

Jednak w użyciu nie dodaje się już prefixu "scope".

$users = App\User::popular()->active()->orderBy('created_at')->get();

Dynamiczne Query Scopes

Czasem możesz znaleźć się w sytuacji kiedy zajdzie potrzeba przekazania do Query Scope jakichś parametrów. Wówczas nie jest to problemem, wystarczy że we wcześniej stworzonej metodzie Query Scope przyjmiesz go jako następny parametr (pierwszy jest instancją query buildera).

public function scopeOfType($query, $type)
{
    return $query->where('type', $type);
}

Teraz możesz go po prostu przekazać do metody Query Scope jako parametr.

To już wszystko

Tyle w temacie Query Scopes w odniesieniu do systemu ORM Eloquent w Laravelu Emotikon uśmiechniętej buźki.

Bardzo fajna mechanika po którą na pewno sięgniesz nie raz. A może już sięgałeś? Sam ostatnio jej użyłem w jednym projekcie i świetnie się sprawdziła. Query Scopes dają nam bardzo duże możliwości i większe pole do popisu, szczególnie że mamy do dyspozycji lokalne, globalne, klasowe, anonimowe i z nimi bądź bez nich... Cudnie Emotikon uśmiechniętej buźki

Dziękuję za lekturę i zapraszam cię do przeczytania innych moich artykułów Emotikon uśmiechniętej buźki. Zostaw proszę jakiś komentarz i podziel się tym artykułem z innymi Emotikon uśmiechniętej buźki.

Bywaj!

Krystian Bogucki

Podobał Ci się ten artykuł?

Jeśli tak, to zarejestruj się aby otrzymywać powiadomienia o nowych artykułach. Nie ujawnię nikomu Twojego adresu!

1 komentarzy... przeczytaj komentarze albo dodaj nowy komentarz


hładini

2018-01-19

Jestem oszolomiony tym ! gz tak trzymaj !!!!!! rzygam php