Probably the most powerful directive to provide search (where
conditions) for your GraphQL queries.
"""
Use Input as Search Conditions for the current Builder.
"""
directive @searchBy
on
| ARGUMENT_DEFINITION
Out of the box directives provides following features:
- Strictly typed - you can define supported operators for each Scalar;
- Eloquent Builder, Query Builder and Custom Builder support;
- Support almost all
where
operators; - Enums support;
not (<condition>)
support;- Relations support (Eloquent Builder only);
- Custom operators support
- easy to use and safe.
Let's start:
scalar Date @scalar(class: "Nuwave\\Lighthouse\\Schema\\Types\\Scalars\\Date")
type Query {
users(where: _ @searchBy): [User!]! @all
comments(where: CommentsQuery @searchBy): [Comment!]! @all
}
input UsersQuery {
id: ID!
name: String!
}
input CommentsQuery {
text: String!
user: UsersQuery
date: Date
}
type User {
id: ID!
name: String!
}
type Comment {
text: String!
user: User @belongsTo
date: Date
}
That's all, just search 😃 (or look at generated GraphQL schema)
query {
# WHERE name = "LastDragon"
users(where: {
field: { name: { equal: "LastDragon" } }
}) {
id
}
# WHERE name != "LastDragon"
users(where: {
field: { name: { notEqual: "LastDragon" } }
}) {
id
}
# WHERE name = "LastDragon" or name = "Aleksei"
users(where: {
anyOf: [
{ field: { name: { equal: "LastDragon" } } }
{ field: { name: { equal: "Aleksei" } } }
]
}) {
id
}
# WHERE NOT (name = "LastDragon" or name = "Aleksei")
users(where: {
not: {
anyOf: [
{ field: { name: { equal: "LastDragon" } } }
{ field: { name: { equal: "Aleksei" } } }
]
}
}) {
id
}
# WHERE date IS NULL
users(where: {
field: { date: { isNull: Yes } }
}) {
id
}
# Relationship: WHERE EXIST (related table)
comments(where: {
field: {
user: {
where: {
field: {
date: { between: { min: "2021-01-01", max: "2021-04-01" } }
}
}
}
}
}) {
id
}
# Relationship: WHERE COUNT (related table) = 2
comments(where: {
field: {
user: {
where: {
field: {
date: { between: { min: "2021-01-01", max: "2021-04-01"} }
}
}
count: {
equal: 2
}
}
}
}) {
id
}
}
As you can see in the example above you can use the special placeholder _
instead of real input
. In this case, @searchBy
will generate input
automatically by the actual type
of the query. Please check the main section of Input type auto-generation to learn more about general conversion rules.
The @searchByIgnored
can be used as Ignored marker.
"""
Marks that field/definition should be excluded.
"""
directive @searchByIgnored
on
| ENUM
| FIELD_DEFINITION
| INPUT_FIELD_DEFINITION
| INPUT_OBJECT
| OBJECT
| SCALAR
There are three types of operators:
-
Comparison - used to compare column with value(s), eg
{equal: "value"}
,{lt: 2}
, etc. To add your own you just need to implementOperator
and add it to type(s); -
Extra - used to add additional fields, by default package provides few Logical operators which allow you to do eg
anyOf([{equal: "a"}, {equal: "b"}])
. Adding your own is the same: implementOperator
and add it toOperators::Extra
type; -
Object - used to create conditions for fields with type
Object
(input
/type
/interface
) and allow implement any logic egwhereHas
,whereDoesntHave
, etc. All the same, but these operators should be explicitly added to the fields/input types, by default theRelationship
operator will be used:type Query { users(where: UsersQuery @searchBy): ID! @all comments(where: CommentsQuery @searchBy): ID! @all } input UsersQuery { id: ID! name: String! } input CommentsQuery { text: String! user: UsersQuery @myComplexOperator }
By default, the package provide list of predefined operators for build-in GraphQL and Lighthouse types. To extend/replace the built-in list, you can use config and/or add directives to type/scalar/enum inside the schema. Directives is the recommended way and have priority over the config.
The package also defines a few own types in addition to the standard GraphQL types:
SearchByOperatorsObject
/Operators::Object
- List of known operators forObject
. If no other directive is found, the first supported operator from the list will be used.SearchByOperatorsNumber
/Operators::Number
- Any operator for this type will be available forInt
andFloat
.SearchByOperatorsNull
/Operators::Null
- Additional operators available for nullable fields.SearchByOperatorsExtra
/Operators::Extra
- List of additional extra operators for all types.SearchByOperatorsEnum
/Operators::Enum
- Default operators for enums.SearchByOperatorsDisabled
/Operators::Disabled
- Disabled operators.
extend scalar SearchByOperatorsEnum
@searchByExtendOperators # Re-use operators for `SearchByOperatorsEnum` from config
@searchByExtendOperators(type: "MyScalar") # Re-use operators from `MyScalar` from schema
scalar MyScalar
@scalar(class: "App\\GraphQL\\Scalars\\MyScalar")
@searchByExtendOperators # Re-use operators for `MyScalar` from config
@searchByExtendOperators(type: "MyScalar") # same
@searchByExtendOperators(type: "Int") # Re-use operators from `Int` from schema
@searchByOperatorEqual # Add package operator
@myOperator # Add custom operator
Keep in mind, when you define/extend the scalar/enum, it will override all existing operators, so if you just want to add new operators, the @searchByExtendOperators
directive should be used.
"""
Extends the list of operators by the operators from the specified
`type` or from the config if `null`.
"""
directive @searchByExtendOperators(
type: String
)
on
| ENUM
| SCALAR
<?php declare(strict_types = 1);
use LastDragon_ru\LaraASP\GraphQL\PackageConfig;
use LastDragon_ru\LaraASP\GraphQL\SearchBy\Definitions\SearchByOperatorBetweenDirective;
use LastDragon_ru\LaraASP\GraphQL\SearchBy\Definitions\SearchByOperatorEqualDirective;
$config = PackageConfig::getDefaultConfig();
// You can define a list of operators for each type
$config->searchBy->operators['Date'] = [
SearchByOperatorEqualDirective::class,
SearchByOperatorBetweenDirective::class,
// MyCustomOperator::class,
];
// Or re-use existing type
$config->searchBy->operators['DateTime'] = [
'Date',
];
// Or re-use built-in type
$config->searchBy->operators['Int'] = [
'Int', // built-in operators for `Int` will be used
// MyCustomOperator::class, // the custom operator will be added
];
// You can also use enum name to redefine default operators for it:
$config->searchBy->operators['MyEnum'] = [
'Boolean',
];
// Return
return $config;