...

20 трика за Laravel Eloquent (част 2)

под повърхноста на Eloquent ORM
преди 3 месеца

11. Подреждане чрез мутатор

Да кажем, че имаме следният мутатор:

function getFullNameAttribute()
{
  return $this->attributes['first_name'] . ' ' . $this->attributes['last_name'];
}

и трябва да подредим резултата по това ново поле "full_name":

// Това няма да работи
$clients = Client::orderBy('full_name')->get();
// Така ще работи - подреждане СЛЕД като сме взели колекцията
$clients = Client::get()->sortBy('full_name');

Залележете, че функцията е различна - sortBy

12. Default ordering in global scope

Какво ще направим, ако искате User::all() винаги да е подредено по полето name? Може да добавим желано подреждане в global scope чрез разглежданият по-рано метод boot

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

    // Order by name ASC
    static::addGlobalScope('order', function (Builder $builder) {
        $builder->orderBy('name', 'asc');
    });
}

повече за Query Scopes може да намерите в документацията: https://laravel.com/docs/7.x/eloquent#query-scopes

13 Сурови SQL заявки

Понякога ни се налага да ползваме SQL заявки, вместо съкратените за Eloquent. Естествено, има и функции за това:

// whereRaw
$orders = DB::table('orders')
    ->whereRaw('price > IF(state = "TX", ?, 100)', [200])
    ->get();

// havingRaw
Product::groupBy('category_id')->havingRaw('COUNT(*) > 1')->get();

// orderByRaw
User::where('created_at', '>', '2016-01-01')
  ->orderByRaw('(updated_at - created_at) desc')
  ->get();

14. Replicate: копие на ред

Накратко, без много обяснения - прави копие на запис в базата:

$task = Tasks::find(1);
$newTask = $task->replicate();
$newTask->save();

15. Chunk() метод за големи таблици

Не е свързано с Eloquent, по-скоро с колекцийте, но пак е мощен инструмент - може да разделите големи резултати на по-малки части. Вместо

$users = User::all();
foreach ($users as $user) {
    // ...

може да използвате

User::chunk(100, function ($users) {
    foreach ($users as $user) {
        // ...
    }
});

16. Опции при създаване на модел

Когато създавате нов модел може да използвате допълнителни опции за създаване и на:

php artisan make:model Company -mcr
// -m за създаване на migration файл
// -c за създаване на контролер
// -r за създаване на ресурси в контролера - това са добавените по подразбиране функции за CRUD

17. Презаписване на полето updated_at при запазване

Знаете ли че модела ->save() приема параметри? Така лесно можем да игнорираме промяната на полето updated_at:

$product = Product::find($id);
$product->updated_at = '2019-01-01 10:00:00';
$product->save(['timestamps' => false]);

18. Какъв е резултата от метода update()?

Знаете ли този код какъв резултат ще върне:

$result = $products->whereNull('category_id')->update(['category_id' => 2]);

Отговорът е - засегнатите редове (affected rows) - така че, ако някога ви потрябва - ще знаете.

19. Трансформиране на скоби в Eloquent заявки

Какво ще направите, ако имате следният микс ако-или в SQL

... WHERE (gender = 'Male' and age >= 18) or (gender = 'Female' and age >= 65)

Как да ги трансформираме в Eloquent? Това е грешният начин:

$q->where('gender', 'Male');
$q->orWhere('age', '>=', 18);
$q->where('gender', 'Female');
$q->orWhere('age', '>=', 65);

Подреждането не е правилно, тук трябва да се използвад под-заявки

$q->where(function ($query) {
    $query->where('gender', 'Male')
        ->where('age', '>=', 18);
})->orWhere(function($query) {
    $query->where('gender', 'Female')
        ->where('age', '>=', 65); 
})

20. orWhere с няколко параметъра

И последно - знаете ли, че orWhere() може да приема масиви Обикновенно пишем:

$q->where('a', 1);
$q->orWhere('b', 2);
$q->orWhere('c', 3);

Но може да стане и по-лесно:

$q->where('a', 1);
$q->orWhere(['b' => 2, 'c' => 3]);