Skip to content

Подгрузка связей ​

allowedIncludes() перечисляет связи, которые может загрузить запрос клиента. Параметр include принимает список имён связей:

php
QueryBuilder::for(User::class)
    ->allowedIncludes('posts', 'permissions')
    ->get();
GET /users?include=posts,permissions

Связи загружаются жадно через with(). Include не из списка выбрасывает InvalidIncludeQuery.

Вложенные связи ​

php
->allowedIncludes('posts.comments')

Вложенный путь разрешает и каждый свой префикс: работают и include=posts, и include=posts.comments.

Другое имя связи ​

php
use MyProgs\QueryBuilder\AllowedInclude;

AllowedInclude::relationship('profile', 'userProfile')

Клиент подгружает profile, запрос загружает userProfile.

Агрегаты ​

Имя связи в allowedIncludes() также разрешает её количество и наличие:

GET /users?include=postsCount,postsExists

Они загружаются через withCount() и withExists(), так что каждый пользователь получает posts_count и posts_exists. Вложенные пути разрешают агрегаты только своей первой связи. Суффиксы берутся из ключа конфигурации suffixes.

Чтобы разрешить агрегат без самой связи, укажите его отдельно:

php
->allowedIncludes('postsCount', AllowedInclude::exists('postsExists'))

Остальные агрегаты принимают связь и колонку:

php
AllowedInclude::min('postsViewsMin', 'posts', 'views'),
AllowedInclude::max('postsViewsMax', 'posts', 'views'),
AllowedInclude::sum('postsViewsSum', 'posts', 'views'),
AllowedInclude::avg('postsViewsAvg', 'posts', 'views'),

Они загружаются через withMin(), withMax(), withSum() и withAvg(), так что атрибут называется posts_min_views и так далее. Каждый агрегат принимает необязательное замыкание, ограничивающее запрос связанной модели:

php
AllowedInclude::count('publishedPostsCount', 'posts', fn ($query) => $query->where('published', true))

Include-callback ​

php
AllowedInclude::callback('posts', fn ($query) => $query->where('published', true))

Замыкание ограничивает жадную загрузку связи: оно передаётся в with() как ['posts' => $closure]. Третий аргумент задаёт имя связи, если оно отличается от имени include.

Собственные классы include ​

Реализуйте MyProgs\QueryBuilder\Includes\IncludeInterface и зарегистрируйте его через custom():

php
use Illuminate\Database\Eloquent\Builder;
use MyProgs\QueryBuilder\Includes\IncludeInterface;

class AggregateInclude implements IncludeInterface
{
    public function __construct(protected string $column, protected string $function) {}

    public function __invoke(Builder $query, string $relations): void
    {
        $query->withAggregate($relations, $this->column, $this->function);
    }
}
php
AllowedInclude::custom('comments_sum_votes', new AggregateInclude('votes', 'sum'), 'comments')

Класс получает корневой запрос и имя связи — третий аргумент.

Поля подгруженных связей ​

С allowedFields() клиент может сузить колонки подгруженной связи, а ключи, нужные связи, добавляются автоматически. См. Выбор полей.