feat(graphql): relation filter (#1060)

This commit is contained in:
Kyrch
2026-01-26 18:28:15 -03:00
committed by GitHub
parent 9fb9c5e11b
commit 1f8b9daa1f
3 changed files with 64 additions and 7 deletions
@@ -10,11 +10,13 @@ use App\Enums\GraphQL\ComparisonOperator;
use App\Enums\GraphQL\LogicalOperator;
use App\GraphQL\Filter\Filter;
use App\GraphQL\Schema\Enums\FilterableColumns;
use App\GraphQL\Schema\Fields\Base\CountField;
use App\GraphQL\Schema\Fields\Field;
use App\GraphQL\Schema\Types\EloquentType;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
class WhereConditionsFilterCriteria extends FilterCriteria
{
@@ -62,12 +64,22 @@ class WhereConditionsFilterCriteria extends FilterCriteria
if (filled($fieldName) && filled($value)) {
$field = $this->filterableFields->get($fieldName);
$builder->where(
$field->getColumn(),
ComparisonOperator::unstrictCoerce(Arr::get($where, 'operator'))->value,
Arr::first($field->getFilter()->getFilterValues(Arr::wrap($value))),
$logical->value
);
if ($field instanceof CountField) {
$builder->withCount(Str::replace('Count', '', $field->getName()));
$builder->having(
Str::snake($field->getColumn()),
ComparisonOperator::unstrictCoerce(Arr::get($where, 'operator'))->value,
Arr::first($field->getFilter()->getFilterValues(Arr::wrap($value))),
$logical->value
);
} else {
$builder->where(
$field->getColumn(),
ComparisonOperator::unstrictCoerce(Arr::get($where, 'operator'))->value,
Arr::first($field->getFilter()->getFilterValues(Arr::wrap($value))),
$logical->value
);
}
}
$builder->where(function (Builder $builder) use ($where): void {
+38
View File
@@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
namespace App\GraphQL\Filter;
use GraphQL\Type\Definition\Type;
use Illuminate\Support\Arr;
class RelationFilter extends Filter
{
public function getBaseType(): Type
{
return Type::int();
}
/**
* Convert filter values if needed. By default, no conversion is needed.
*/
protected function convertFilterValues(array $filterValues): array
{
return Arr::map(
$filterValues,
fn (string $filterValue): ?int => filter_var($filterValue, FILTER_VALIDATE_INT, FILTER_NULL_ON_FAILURE)
);
}
/**
* Get the validation rules for the filter.
*/
protected function getRules(): array
{
return [
'required',
'integer',
];
}
}
@@ -5,13 +5,15 @@ declare(strict_types=1);
namespace App\GraphQL\Schema\Fields\Base;
use App\Contracts\GraphQL\Fields\DisplayableField;
use App\Contracts\GraphQL\Fields\FilterableField;
use App\Contracts\GraphQL\Fields\SortableField;
use App\Enums\GraphQL\SortType;
use App\GraphQL\Filter\RelationFilter;
use App\GraphQL\Schema\Fields\Field;
use GraphQL\Type\Definition\ResolveInfo;
use GraphQL\Type\Definition\Type;
class CountField extends Field implements DisplayableField, SortableField
class CountField extends Field implements DisplayableField, FilterableField, SortableField
{
public function __construct(
protected string $relation,
@@ -45,6 +47,11 @@ class CountField extends Field implements DisplayableField, SortableField
return $this->relation;
}
public function getFilter(): RelationFilter
{
return new RelationFilter($this->getName(), $this->getColumn());
}
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo): mixed
{
return $root->hasAttribute($attribute = "{$this->relation}_count")