web-dev-qa-db-fra.com

Comment interroger tous les champs de type GraphQL sans écrire une longue requête?

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.

83
BlackSigma

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.

65
Peter Horne

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.

57
Mark Chackerian

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
    }
}
26
tommy

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.

7
Tyrone Wilson