Digging Deeper
Pivot Filters
Overview
Filter::field()
filters can be marked as pivot filters if you want the filter to be applied to a column on the intermediate table linking the models.
You must specify the parent model fqcn.
public function allowedFilters(): AllowedFilterList
{
return Filter::only(
Filter::field('tagged_by', [FilterType::EQUAL])->pivot(Post::class),
);
}
BelongsToMany
In the below example of class Post
and class Tag
.
- The pivot filter can only be used when in the context of the
posts
ortags
relationship.
class Post extends Model implements IsFilterable
{
use Filterable;
public function tags(): BelongsToMany
{
return $this->belongsToMany(Tag::class);
}
public function allowedFilters(): AllowedFilterList
{
return Filter::only(
Filter::field('tagged_by', [FilterType::EQUAL])->pivot(Tag::class),
Filter::relation('tags', [FilterType::HAS])->includeRelationFields()
);
}
}
class Tag extends Model implements IsFilterable
{
use Filterable;
public function posts(): BelongsToMany
{
return $this->belongsToMany(Post::class);
}
public function allowedFilters(): AllowedFilterList
{
return Filter::only(
Filter::field('tagged_by', [FilterType::EQUAL])->pivot(Post::class),
Filter::relation('posts', [FilterType::HAS])->includeRelationFields()
);
}
}
// Applying `tagged_by` filter within `tags` `$has` relation filter.
// Allowed
Post::filter([
[
'type' => '$has',
'target' => 'tags',
'value' => [
[
'type' => '$eq',
'target' => 'tagged_by',
'value' => 'admin',
]
]
]
]);
// Applying `tagged_by` filter within `posts` `$has` relation filter.
// Allowed
Tag::filter([
[
'type' => '$has',
'target' => 'posts',
'value' => [
[
'type' => '$eq',
'target' => 'tagged_by',
'value' => 'admin',
]
]
]
]);
// Applying `tagged_by` filter when not in context of `tags` `$has` relation filter.
// throws DeniedFilterException.
Post::filter([
[
'type' => '$eq',
'target' => 'tagged_by',
'value' => 'admin',
]
]);
// Applying `tagged_by` filter when not in context of `posts` `$has` relation filter.
// throws DeniedFilterException.
Tag::filter([
[
'type' => '$eq',
'target' => 'tagged_by',
'value' => 'admin',
]
]);
// Applying `tagged_by` filter when in context of another BelongsToMany relation
// but User::class not defined in the ->pivot() method in the tags model.
// throws DeniedFilterException.
User::filter([
[
'type' => '$has',
'target' => 'tags',
'value' => [
[
'type' => '$eq',
'target' => 'tagged_by',
'value' => 'admin',
]
]
]
]);
Many To Many (Polymorphic)
When defining a pivot filter for MorphToMany
relations, you can specify a list of models in the ->pivot()
method.
class Epic extends Model implements IsFilterable
{
// ...
public function allowedFilters(): AllowedFilterList
{
return Filter::only(
Filter::relation('labels', [FilterType::HAS])->includeRelationFields()
);
}
}
class Issue extends Model implements IsFilterable
{
// ...
public function allowedFilters(): AllowedFilterList
{
return Filter::only(
Filter::relation('labels', [FilterType::HAS])->includeRelationFields()
);
}
}
class Label extends Model implements IsFilterable
{
// ...
public function allowedFilters(): AllowedFilterList
{
return Filter::only(
Filter::field('labeled_by', [FilterType::EQUAL])->pivot(Epic::class, Issue::class)
);
}
}