How to implement ordeBy functionality using GraphQL with the nuwave / lighthouse dependency?
I searched in several forums, without example events
You can do that easily with any custom resolver, using a defined argument to control the query.
If you want a reusable way that works with the built-in resolvers that Lighthouse offers, you can go for a custom ArgFilterDirective, similar to https://github.com/nuwave/lighthouse/blob/master/src/Schema/Directives/Args/EqDirective.php
It should be pretty simple to implement an @orderBy directive, accepting PRs.
@spawnia Considering paginate/ filters / order is a common stuff, do you think is useful to provide it from Lighthouse core? Would be hard to implement it with one shot (all in one) ?
Usually paginate / filter / order lives together.
I think we should have it in the core.
It should be fairly simple to implement orderBy, considering @paginate and the ArgumentFilterDirective class already exist.
How about this syntax:
type Query {
posts(orderByTimePosted: SortOrder @orderBy): [Post!]!
}
enum SortOrder {
ASC
DESC
}
So, SortOrder would be a builtin scalar?
Any update on this?
How about this: https://gist.github.com/Arkitecht/6ec3a9e850273214d7803093271ef625
Can be used by:
users(
order_by: String @orderBy
): [User!]! @all
and called with:
query {
users(order_by:"last_name") {
first_name,
last_name
}
}
OR
query {
users(order_by:"last_name,desc") {
first_name,
last_name
}
}
I'd vote for a flexible solution with supports sorting by multiple fields. e.g:
query {
users(orderBy: ["firstName:desc", "lastName:desc"]) {
firstName,
lastName
}
}
Which would be untyped though.
Typed version could look like:
type Query {
users(orderBy: [SortOption!]! @orderBy): [User!]!
}
input SortOption {
field: String
order: SortOrder
}
enum SortOrder {
ASC
DESC
}
query {
users(orderBy: [{field: "firstName", order: DESC}, {field: "lastName", order: DESC]) {
firstName,
lastName
}
}
@jbbr's approach seems pretty clean.
Could SortOrder and SortOption be built in?
I've been trying to build my own implementation for this, but i'm stuck. I've added the Directive in the Directives folder but it does not apply its logic.
<?php
namespace App\Http\Graphql\Directives;
use Illuminate\Database\Eloquent\Builder;
use Nuwave\Lighthouse\Support\Contracts\ArgFilterDirective;
/**
* Class OrderBy
*
* @package App\Http\Graphql\Directives
*/
class OrderByDirective implements ArgFilterDirective
{
/**
* @param \Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder $builder
* @param string $columnName
* @param mixed $value
*
* @return \Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder
*/
public function applyFilter($builder, string $columnName, $value)
{
return $builder->orderBy($columnName, $value);
}
/**
* Does this filter combine the values of multiple input arguments into one query?
*
* This is true for filter directives such as "whereBetween" that expects two
* different input values, given as separate arguments.
*
* @return bool
*/
public function combinesMultipleArguments(): bool
{
return false;
}
/**
* Name of the directive.
*
* @return string
*/
public function name()
{
return 'orderBy';
}
}
input SortOption {
field: String!
order: SortOrder!
}
enum SortOrder {
ASC
DESC
}
type Query{
suppliers(sortOptions: [SortOption!]! @orderBy): [Supplier!] @paginate
}
When I test it with xdebug, it never hits the applyFilter function. Do I need to register it somewhere? When I add a constructor and place a breakpoint inside of it, it breaks multiple times. So the directive is found. Also, the schema is valid according to artisan lighthouse:validate-schema
@megawubs can you try without @paginate using something like @all instead?
@spawnia When I remove @paginate and add @all the @orderBy Directive is still not applied
Using dev-master?
Yes, because the project is uses Laravel 5.8
You might have an easier time at trying out the implementation if you fork this project and go from there. Here are a few pointers of what files to look at:
https://github.com/nuwave/lighthouse/blob/master/src/Schema/Factories/DirectiveFactory.php
https://github.com/nuwave/lighthouse/blob/master/src/Execution/QueryFilter.php
https://github.com/nuwave/lighthouse/blob/master/tests/Integration/Schema/Directives/Args/QueryFilterDirectiveTest.php
Most helpful comment
I'd vote for a flexible solution with supports sorting by multiple fields. e.g:
Which would be untyped though.
Typed version could look like: