Поддержите проект сделав пожертвование.

Кастомные Query Builders в Laravel

В Laravel часто бывает, что модели содержат слишком много бизнес-логики. К счастью, можно создать собственные классы Query Builders, чтобы сделать модели более “тонкими” и чистыми. В этой статье мы рассмотрим, как создавать и использовать кастомные Query Builders на примере модели Book.

Создание собственного Query Builder Начнем с создания класса BookBuilder. Этот класс будет расширять Illuminate\Database\Eloquent\Builder, чтобы унаследовать всю функциональность стандартного билдера Laravel.

<?php

namespace App\Builders;

use App\Models\User;
use Illuminate\Database\Eloquent\Builder;

class BookBuilder extends Builder
{
    public function wherePublished(): self
    {
        return $this->where('publish_at', '<=', now());
    }

    public function whereAuthor(User $user): self
    {
        return $this->where('author_id', $user->id);
    }

    public function wherePriceBetween(float $from, float $to): self
    {
        return $this->whereBetween('price', [$from, $to]);
    }

    public function whereContains(string $searchTerm): self
    {
        return $this->where(function ($query) use ($searchTerm) {
            $query->where('title', 'LIKE', "%$searchTerm%")
                ->orWhere('description', 'LIKE', "%$searchTerm%");
        });
    }

    public function orderByRatings(): self
    {
        return $this->withAvg('ratings as average_rating', 'rating')
            ->orderByDesc('average_rating');
    }

    public function mostPopular(int $count): self
    {
        return $this->orderByRatings()
            ->take($count);
    }

    public function publish(): self
    {
        $this->model->publish_at = now();
        $this->model->save();

        return $this;
    }
}

Интеграция кастомного Query Builder в модель

Теперь нужно сообщить Laravel, чтобы он использовал наш кастомный билдер при создании запросов для модели Book. Для этого мы переопределим метод newEloquentBuilder в модели.

<?php

namespace App\Models;

use App\Builders\BookBuilder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;

class Book extends Model
{
    use HasFactory;

    public function author(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

    public function ratings(): HasMany
    {
        return $this->hasMany(Rating::class);
    }

    public function newEloquentBuilder($query): BookBuilder
    {
        return new BookBuilder($query);
    }
}

Теперь каждый раз, когда вы начинаете строить запрос с Book::something(), вы будете получать экземпляр BookBuilder.

Применение кастомного Query Builder в контроллере

Рассмотрим пример контроллера, который использует наш кастомный Query Builder для фильтрации и сортировки книг.

<?php

namespace App\Http\Controllers;

use App\Models\Book;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;

/**
 * Class BookController
 */
class BookController extends Controller
{
    public function index(Request $request): JsonResponse
    {
        $books = Book::query()
            ->wherePublished()
            ->when($request->authorId, fn($query) => $query->whereAuthor(User::find($request->authorId)))
            ->when($request->fromPrice, fn($query) => $query->wherePriceBetween($request->fromPrice, $request->toPrice))
            ->orderByRatings()
            ->get();

        return response()->json($books);
    }

    public function popular(): JsonResponse
    {
        $books = Book::mostPopular(5)->get();

        return response()->json($books);
    }

    public function publish(Book $book): JsonResponse
    {
        $book->publish();

        return response()->json(['status' => 'success']);
    }
}

Расширение функциональности

С помощью кастомных Query Builders вы можете легко добавлять новые методы для манипуляции данными. Например, метод для публикации всех книг:

<?php

namespace App\Builders;

class BookBuilder extends Builder
{
    // Другие методы...

    public function publishAll(): self
    {
        $this->whereNotPublished()
            ->update(['publish_at' => now()]);

        return $this;
    }

    protected function whereNotPublished(): self
    {
        return $this->where('publish_at', '>', now());
    }
}

Заключение

Кастомные Query Builders предоставляют гибкость и возможность создавать и комбинировать сложные запросы, инкапсулируя логику запросов в отдельные классы. Это делает код более чистым, структурированным и легко расширяемым, что способствует лучшей поддерживаемости и удобочитаемости вашего приложения.

Использование кастомных Query Builders также позволяет лучше организовать бизнес-логику и делает ваши модели более “тонкими”. Этот подход может существенно улучшить качество кода и облегчить его поддержку.

Источник: https://martinjoo.dev/build-your-own-laravel-query-builders

Inn_100_gramm

Если вы видите это, значит, я еще не придумал, что написать.

2

Вакансии

Спонсоры

Помощь в разработке вашего проекта на Laravel

Независимо от сложности проекта эти кампании помогают сообществу и всем его участникам воплощать идеи в элегантные приложения.

Присоединиться

Инструменты для управления эмоциями, которые помогают людям контролировать свою жизнь и лучше понимать себя.

Перейти

Подкасты c зажигательными эпизодами, которые заставят задуматься и приведут к новым перспективам.

Перейти