$sortByColumns * * @throws ClientValidationException * @throws InvalidArgumentException */ public function handleBuilder(QueryBuilder|EloquentBuilder|Relation $builder, $sortByColumns): QueryBuilder|EloquentBuilder|Relation { $sortableColumns = json_decode($this->directiveArgValue('columns'), true); foreach ($sortByColumns as $sortByColumn) { $column = Arr::pull($sortByColumn, 'column'); $direction = Arr::pull($sortByColumn, 'direction'); $object = collect($sortableColumns) ->first(fn (array $value) => $value['column'] === $column); if ($object === null) { throw new ClientValidationException("The column '{$column}' is not available for ordering."); } $sortType = SortType::from(Arr::get($object, 'sortType')); if ($sortType === SortType::ROOT) { $builder->orderBy($column, $direction); } if ($sortType === SortType::AGGREGATE) { $relation = Arr::get($object, 'relation'); if ($relation === null) { throw new InvalidArgumentException("The 'relation' argument is required for the @{$this->name()} directive with aggregate sort type."); } $builder->withAggregate([ "$relation as {$relation}_value" => function ($query) use ($direction) { $query->orderBy('value', $direction); }, ], 'value'); $builder->orderBy("{$relation}_value", $direction); } } return $builder; } }