Supposons que vous ayez un type GraphQL et qu'il comporte de nombreux champs. Comment interroger tous les champs sans écrire une longue requête qui inclut les noms de tous les champs?
Par exemple, si j'ai ces champs:
public function fields()
{
return [
'id' => [
'type' => Type::nonNull(Type::string()),
'description' => 'The id of the user'
],
'username' => [
'type' => Type::string(),
'description' => 'The email of user'
],
'count' => [
'type' => Type::int(),
'description' => 'login count for the user'
]
];
}
Pour interroger tous les champs, la requête ressemble généralement à ceci:
FetchUsers{users(id:"2"){id,username,count}}
Mais je veux un moyen d'avoir les mêmes résultats sans écrire tous les champs, quelque chose comme ceci:
FetchUsers{users(id:"2"){*}}
//or
FetchUsers{users(id:"2")}
Existe-t-il un moyen de faire cela dans GraphQL?
J'utilise la bibliothèque Folkloreatelier/laravel-graphql.
Malheureusement, ce que vous voudriez faire n'est pas possible. GraphQL exige que vous soyez explicite sur la spécification des champs à renvoyer de votre requête.
Oui, vous pouvez faire ceci en utilisant introspection . Faites une requête GraphQL comme (pour le type UserType )
{
__type(name:"UserType") {
fields {
name
description
}
}
}
et vous obtiendrez une réponse du type (les noms de champs réels dépendront de votre définition de schéma/type)
{
"data": {
"__type": {
"fields": [
{
"name": "id",
"description": ""
},
{
"name": "username",
"description": "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only."
},
{
"name": "firstName",
"description": ""
},
{
"name": "lastName",
"description": ""
},
{
"name": "email",
"description": ""
},
( etc. etc. ...)
]
}
}
}
Vous pouvez ensuite lire cette liste de champs dans votre client et créer dynamiquement une seconde requête GraphQL pour obtenir tous ces champs.
Cela suppose que vous connaissiez le nom du type pour lequel vous voulez obtenir les champs. Si vous ne connaissez pas le type, vous pouvez obtenir tous les types et champs en utilisant l'introspection, comme
{
__schema {
types {
name
fields {
name
description
}
}
}
}
REMARQUE: Il s'agit des données GraphQL sur réseau. Vous êtes seul pour savoir comment lire et écrire avec votre client actuel. Votre bibliothèque javascript graphQL peut déjà utiliser l'introspection dans une certaine mesure, par exemple la commande apollo codegen utilise l'introspection pour générer des types.
Je suppose que la seule façon de faire est d'utiliser des fragments réutilisables:
fragment UserFragment on Users {
id
username
count
}
FetchUsers {
users(id: "2") {
...UserFragment
}
}
J'ai rencontré le même problème lorsque j'ai eu besoin de charger des données d'emplacement que j'avais sérialisées dans la base de données à partir de l'API Google Places. Généralement, je voudrais tout faire pour que cela fonctionne avec les cartes, mais je ne voulais pas avoir à spécifier tous les champs à chaque fois.
Je travaillais dans Ruby, je ne peux donc pas vous donner l'implémentation de PHP, mais le principe devrait être le même.
J'ai défini un type scalaire personnalisé appelé JSON, qui ne renvoie qu'un objet JSON littéral.
L'implémentation Ruby était comme ça (en utilisant graphql-Ruby)
module Graph
module Types
JsonType = GraphQL::ScalarType.define do
name "JSON"
coerce_input -> (x) { x }
coerce_result -> (x) { x }
end
end
end
Ensuite, je l'ai utilisé pour nos objets comme
field :location, Types::JsonType
J'utiliserais cela très parcimonieusement, en l'utilisant seulement là où vous savez que vous avez toujours besoin de tout l'objet JSON (comme je l'ai fait dans mon cas). Autrement, c'est détruire l'objet de GraphQL plus généralement.