Construire un serveur GraphQL avec Laravel
Publié: 2022-03-11Au cas où vous ne le connaîtriez pas encore, GraphQL est un langage de requête utilisé pour interagir avec votre API qui offre certains avantages par rapport aux architectures alternatives telles que REST. GraphQL est extrêmement pratique lorsqu'il est utilisé pour servir de point de terminaison pour les applications mobiles et d'une seule page. GraphQL vous permet d'interroger des données imbriquées et associées dans une requête avec une relative facilité, permettant aux développeurs d'obtenir les données exactes dont ils ont besoin en un seul aller-retour vers le serveur.
Laravel est un framework Web PHP populaire et opiniâtre. Il fournit de nombreux outils intégrés pour rendre les applications opérationnelles rapidement, mais il permet également aux développeurs d'échanger leurs propres implémentations contre les interfaces intégrées de Laravel lorsqu'ils le souhaitent.
Bien que les communautés entourant à la fois GraphQL et Laravel se soient considérablement développées depuis qu'elles sont open source, la documentation expliquant comment utiliser ces deux technologies ensemble est encore assez rare.
Donc, dans ce tutoriel, je vais vous montrer comment créer votre propre serveur GraphQL en utilisant Laravel.
Aperçu du projet
Avant de commencer, nous devrons nous familiariser avec le projet que nous essayons de construire. Pour ce faire, nous allons définir nos ressources et créer notre schéma GraphQL, que nous utiliserons plus tard pour servir notre API.
Ressources du projet
Notre application sera composée de deux ressources : Articles et Utilisateurs . Ces ressources seront définies en tant que types d'objets dans notre schéma GraphQL :
type User { id: ID! name: String! email: String! articles: [Article!]! } type Article { id: ID! title: String! content: String! author: User! }
En regardant le schéma, nous pouvons voir que nous avons une relation un-à-plusieurs entre nos deux objets. Les utilisateurs peuvent écrire de nombreux articles, et un article a un auteur (utilisateur) qui lui est assigné.
Maintenant que nos types d'objets sont définis, nous aurons besoin d'un moyen de créer et d'interroger nos données. Définissons donc nos objets de requête et de mutation :
type Query { user(id: ID!): User users: [User!]! article(id: ID!): Article articles: [Article!]! } type Mutation { createUser(name: String!, email: String!, password: String!): User createArticle(title: String!, content: String!): Article }
Mise en place de notre projet Laravel
Maintenant que nous avons défini notre schéma GraphQL, lançons notre projet Laravel opérationnel. Commençons par créer un nouveau projet Laravel via Composer :
$ composer create-project --prefer-dist laravel/laravel laravel-graphql
Juste pour nous assurer que tout fonctionne, démarrons notre serveur et assurons-nous de voir la page par défaut de Laravel :
$ cd laravel-graphql $ php artisan serve Laravel development server started: <http://127.0.0.1:8000>
Modèles de base de données et migrations
Pour les besoins de cet article, nous utiliserons SQLite. Apportons donc les modifications suivantes au fichier .env
par défaut :
DB_CONNECTION=sqlite # DB_HOST= # DB_PORT= # DB_DATABASE=database.sqlite # DB_USERNAME= # DB_PASSWORD=
Ensuite, créons notre fichier de base de données :
$ touch ./database/database.sqlite
Laravel est livré avec un modèle utilisateur et quelques fichiers de migration de base. Ajoutons rapidement une colonne api_token
à notre fichier de migration CreateUsersTable
fourni par Laravel :
/database/migrations/XXXX_XX_XX_000000_create_users_table.php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateUsersTable extends Migration { /** * Run the migrations. */ public function up() { Schema::create('users', function (Blueprint $table) { $table->bigIncrements('id'); $table->string('name'); $table->string('email')->unique(); $table->timestamp('email_verified_at')->nullable(); $table->string('password'); $table->string('api_token', 80)->unique()->nullable()->default(null); $table->rememberToken(); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down() { Schema::dropIfExists('users'); } }
Nous reviendrons à cette colonne supplémentaire plus loin dans l'article lorsque nous arriverons à l'autorisation. Continuons maintenant et créons notre modèle d'article et un fichier de migration pour créer la table associée :
$ php artisan make:model Article -m
Remarque : L'option -m crée un fichier de migration pour notre modèle d'article nouvellement créé.
Apportons quelques ajustements au fichier de migration généré :
use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateArticlesTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('articles', function (Blueprint $table) { $table->bigIncrements('id'); $table->unsignedBigInteger('user_id'); $table->string('title'); $table->text('content'); $table->timestamps(); $table->foreign('user_id')->references('id')->on('users'); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('articles'); } }
Nous avons ajouté une clé étrangère pointant vers l' id
de notre table d' users
ainsi que les colonnes de title
et content
que nous avons définies dans notre schéma GraphQL.
Maintenant que nos fichiers de migration sont définis, allons-y et exécutons-les sur notre base de données :
$ php artisan migrate
Ensuite, mettons à jour nos modèles en définissant les relations nécessaires :
app/User.php namespace App; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable { use Notifiable; /** * The attributes that are mass assignable. * * @var array */ protected $fillable = [ 'name', 'email', 'password', ]; // ... /** * @return \Illuminate\Database\Eloquent\Relations\HasMany */ public function articles() { return $this->hasMany(Article::class); } }
app/Article.php namespace App; use Illuminate\Database\Eloquent\Model; class Article extends Model { /** * The attributes that are mass assignable. * * @var array */ protected $fillable = [ 'title', 'content', ]; /** * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ public function user() { return $this->belongsTo(User::class); } }
Amorçage de la base de données
Maintenant que nos modèles et nos migrations sont configurés, ensemençons notre base de données. Nous allons commencer par créer des classes de départ pour nos articles
et nos tables d' users
:
$ php artisan make:seeder UsersTableSeeder $ php artisan make:seeder ArticlesTableSeeder
Ensuite, configurons-les pour insérer des données factices dans notre base de données SQLite :
database/seeds/UsersTableSeeder.php use App\User; use Illuminate\Database\Seeder; class UsersTableSeeder extends Seeder { /** * Run the database seeds. */ public function run() { \App\User::truncate(); $faker = \Faker\Factory::create(); $password = bcrypt('secret'); \App\User::create([ 'name' => $faker->name, 'email' => '[email protected]', 'password' => $password, ]); for ($i = 0; $i < 10; ++$i) { \App\User::create([ 'name' => $faker->name, 'email' => $faker->email, 'password' => $password, ]); } } }
database/seeds/ArticlesTableSeeder.php use App\Article; use Illuminate\Database\Seeder; class ArticlesTableSeeder extends Seeder { /** * Run the database seeds. */ public function run() { \App\Article::truncate(); \App\Article::unguard(); $faker = \Faker\Factory::create(); \App\User::all()->each(function ($user) use ($faker) { foreach (range(1, 5) as $i) { \App\Article::create([ 'user_id' => $user->id, 'title' => $faker->sentence, 'content' => $faker->paragraphs(3, true), ]); } }); } }
/database/seeds/DatabaseSeeder.php use Illuminate\Database\Seeder; class DatabaseSeeder extends Seeder { /** * Seed the application's database. * * @return void */ public function run() { $this->call(UsersTableSeeder::class); $this->call(ArticlesTableSeeder::class); } }
Enfin, allons-y et exécutons nos semoirs de base de données pour obtenir des données dans notre base de données :
$ php artisan db:seed
Phare de Laravel et serveur GraphQL
Maintenant que notre base de données et nos modèles sont configurés, il est temps de commencer à développer notre serveur GraphQL. Actuellement, plusieurs solutions sont disponibles pour Laravel, mais pour cet article, nous allons utiliser Lighthouse.
Lighthouse est un package que j'ai créé il y a quelques années et qui a récemment bénéficié d'un soutien incroyable de la part de la communauté grandissante qui l'entoure. Il permet aux développeurs de configurer rapidement un serveur GraphQL à l'aide de Laravel avec peu de passe-partout tout en étant suffisamment flexible pour permettre aux développeurs de le personnaliser pour répondre aux besoins de presque tous les projets.
Commençons par insérer le package dans notre projet :
$ composer require nuwave/lighthouse:"3.1.*"
Ensuite, publions le fichier de configuration de Lighthouse :
$ php artisan vendor:publish --provider="Nuwave\Lighthouse\LighthouseServiceProvider" --tag=config
Remarque : Vous pouvez également choisir de publier le fichier de schéma par défaut de Lighthouse en supprimant simplement l'option --tag=config
. Mais pour les besoins de cet article, nous allons créer notre fichier de schéma à partir de zéro.
Si nous jetons un coup d'œil au fichier config/lighthouse.php
, vous remarquerez un paramètre utilisé pour enregistrer notre fichier de schéma auprès de Lighthouse :
'schema' => [ 'register' => base_path('graphql/schema.graphql'), ],
Alors allons-y et créons notre fichier de schéma et configurons notre type d'objet utilisateur et notre requête :
$ mkdir graphql $ touch ./graphql/schema.graphql /graphql/schema.graphql type User { id: ID! name: String! email: String! } type Query { user(id: ID! @eq): User @find users: [User!]! @all }
Vous remarquerez que notre schéma ressemble à celui que nous avons défini précédemment, sauf que nous avons ajouté des identifiants appelés directives de schéma.
Prenons un moment pour décomposer notre schéma défini. Notre première définition est un type d'objet appelé User
qui a une relation avec notre modèle éloquent App\User
. Nous avons défini l' id
, le name
et l'e- email
comme des champs pouvant être interrogés sur nos modèles User
. Autrement, cela signifie que les colonnes password
, created_at
et updated_at
sont des champs qui ne peuvent pas être interrogés à partir de notre API.
Ensuite, nous avons notre type de Query
qui est un point d'entrée dans notre API et peut être utilisé pour interroger des données. Notre premier champ est le champ users
qui renvoie un tableau de types d'objets User
. La directive @all
indique à Lighthouse d'exécuter une requête Eloquent, en utilisant notre modèle User
et d'obtenir tous les résultats. Ce serait la même chose que d'exécuter ce qui suit :
$users = \App\User::all();
Remarque : Lighthouse sait rechercher un modèle dans l'espace de noms \App\User
en raison de l'option d' namespaces
de noms définie dans son fichier de configuration.
Notre deuxième champ défini sur notre type de requête est l'appel user
, qui prend un id
comme argument et renvoie un seul type d'objet User
. Nous avons également ajouté deux directives pour aider Lighthouse à créer automatiquement une requête pour nous et à renvoyer un seul modèle User
. La directive @eq
indique à Lighthouse d'ajouter un where sur notre colonne id
, et la directive @find
indique à Lighthouse de renvoyer un seul résultat. Pour écrire cette requête à l'aide du générateur de requêtes de Laravel, cela ressemblerait à ceci :
$user = \App\User::where('id', $args['id'])->first();
Interroger notre API GraphQL
Maintenant que nous avons un aperçu de la façon dont Lighthouse utilise notre schéma pour créer des requêtes, exécutons notre serveur et commençons à interroger les données. Nous allons commencer par exécuter notre serveur :
$ php artisan serve Laravel development server started: <http://127.0.0.1:8000>
Pour interroger un point de terminaison GraphQL, vous pouvez exécuter la commande cURL dans le terminal ou un client standard tel que Postman. Cependant, pour bénéficier de tous les avantages de GraphQL (tels que la saisie semi-automatique, la mise en évidence des erreurs, la documentation, etc., nous utiliserons GraphQL Playground (versions téléchargeables ici).
Lors du démarrage de Playground, cliquez sur l'onglet "URL Endpoint" et saisissez http://localhost:8000/graphql pour pointer GraphQL Playground vers notre serveur. Sur le côté gauche de l'éditeur, nous pouvons interroger nos données, alors commençons par demander tous les utilisateurs avec lesquels nous avons ensemencé la base de données :
{ users { id email name } }
Lorsque vous appuyez sur le bouton de lecture au milieu de l'IDE (ou cliquez sur Ctrl+Entrée ), vous verrez la sortie JSON de notre serveur sur le côté droit, qui ressemblera à ceci :
{ "data": { "users": [ { "id": "1", "email": "[email protected]", "name": "Carolyn Powlowski" }, { "id": "2", "email": "[email protected]", "name": "Elouise Raynor" }, { "id": "3", "email": "[email protected]", "name": "Mrs. Dejah Wiza" }, ... ] } }
Remarque : Parce que nous avons utilisé Faker pour ensemencer notre base de données, les données dans les champs de l'e- email
et du name
seront différentes.
Essayons maintenant d'interroger un seul utilisateur :
{ user(id: 1) { email name } }
Et nous obtiendrons la sortie suivante pour un seul utilisateur :
{ "data": { "user": { "email": "[email protected]", "name": "Carolyn Powlowski" } } }
Interroger des données comme celle-ci est agréable pour commencer, mais il est très peu probable que vous soyez dans un projet où vous voudriez interroger toutes vos données, alors essayons d'ajouter une pagination. Lorsque nous parcourons la large gamme de directives intégrées de Lighthouse, nous avons une directive @paginate
à notre disposition, alors mettons à jour l'objet de requête de notre schéma comme suit :

type Query { user(id: ID! @eq): User @find users: [User!]! @paginate }
Si nous rechargeons GraphQL Playground ( Ctrl/Cmd + R ) et essayons à nouveau la requête de nos users
, vous remarquerez que nous recevons un message d'erreur indiquant Cannot query field "id" on type "UserPaginator"
, alors que s'est-il passé ? Dans les coulisses, Lighthouse manipule notre schéma pour que nous obtenions un ensemble paginé de résultats et le fait en modifiant le type de retour de notre champ users
.
Examinons de plus près en inspectant notre schéma dans l'onglet "Docs" de GraphQL Playground. Si vous regardez le champ users
, il renvoie un UserPaginator
qui renvoie un tableau d'utilisateurs et un type PaginatorInfo
défini par Lighthouse :
type UserPaginator { paginatorInfo: PaginatorInfo! data: [User!]! } type PaginatorInfo { count: Int! currentPage: Int! firstItem: Int hasMorePages: Boolean! lastItem: Int lastPage: Int! perPage: Int! total: Int! }
Si vous connaissez la pagination intégrée de Laravel, les champs disponibles dans le type PaginatorInfo
probablement très familiers. Ainsi, pour interroger deux utilisateurs, obtenir le nombre total d'utilisateurs dans le système et vérifier que nous avons plus de pages à parcourir, nous enverrions la requête suivante :
{ users(count:2) { paginatorInfo { total hasMorePages } data { id name email } } }
Ce qui nous fournira la réponse suivante :
{ "data": { "users": { "paginatorInfo": { "total": 11, "hasMorePages": true }, "data": [ { "id": "1", "name": "Carolyn Powlowski", "email": "[email protected]" }, { "id": "2", "name": "Elouise Raynor", "email": "[email protected]" }, ] } } }
Des relations
Généralement, lors du développement d'une application, une grande partie de vos données est liée. Dans notre cas, un User
peut écrire de nombreux Articles
, ajoutons donc cette relation à notre type d'utilisateur et définissons notre type d' Article
:
type User { id: ID! name: String! email: String! articles: [Article!]! @hasMany } type Article { id: ID! title: String! content: String! }
Ici, nous utilisons une autre directive de schéma fournie par Lighthouse @hasMany
, qui indique à Lighthouse que notre modèle User
a une \Illuminate\Database\Eloquent\Relations\HasMany
avec le modèle Article
.
Interrogeons maintenant notre relation nouvellement définie :
{ user(id:1) { articles { id title } } }
Cela nous fournira la réponse suivante :
{ "data": { "user": { "articles": [ { "id": "1", "title": "Aut velit et temporibus ut et tempora sint." }, { "id": "2", "title": "Voluptatem sed labore ea voluptas." }, { "id": "3", "title": "Beatae sit et maxime consequatur et natus totam." }, { "id": "4", "title": "Corrupti beatae cumque accusamus." }, { "id": "5", "title": "Aperiam quidem sit esse rem sed cupiditate." } ] } } }
Enfin, inversons notre relation et ajoutons notre relation d' author
à notre type d'objet Article
en utilisant la directive de schéma @belongsTo
de Lighthouse ainsi que la mise à jour de notre Query
:
type Article { id: ID! title: String! content: String! author: User! @belongsTo(relation: "user") } type Query { user(id: ID! @eq): User @find users: [User!]! @paginate article(id: ID! @eq): Article @find articles: [Article!]! @paginate }
Vous verrez que nous avons ajouté un argument de relation
facultatif à la directive @belongsTo
. Cela indique à Lighthouse d'utiliser la relation user
du modèle Articles
et de l'affecter au champ author
.
Maintenant, recherchons une liste d'articles et récupérons leur auteur associé :
{ articles(count:2) { paginatorInfo { total hasMorePages } data { id title author { name email } } } }
Et nous devrions obtenir ce qui suit de notre serveur :
{ "data": { "articles": { "paginatorInfo": { "total": 55, "hasMorePages": true }, "data": [ { "id": "1", "title": "Aut velit et temporibus ut et tempora sint.", "author": { "name": "Carolyn Powlowski", "email": "[email protected]" } }, { "id": "2", "title": "Voluptatem sed labore ea voluptas.", "author": { "name": "Carolyn Powlowski", "email": "[email protected]" } } ] } } }
Mutation GraphQL
Maintenant que nous pouvons interroger nos données, créons quelques mutations pour créer de nouveaux utilisateurs et articles. Commençons par notre modèle utilisateur :
type Mutation { createUser( name: String! email: String! @rules(apply: ["email", "unique:users"]) password: String! @bcrypt @rules(apply: ["min:6"]) ): User @create }
Décomposons maintenant cette définition de schéma. Nous avons créé une mutation appelée createUser
qui prend trois arguments ( name
, email
et password
). Nous avons appliqué la directive @rules
à nos arguments d'e- email
et de password
de passe. Cela peut sembler un peu familier car il est similaire à la logique de validation que Laravel fournit pour ses contrôleurs.
Ensuite, nous avons attaché la directive @bcrypt
à notre champ de password
de passe. Cela chiffrera le mot de passe avant qu'il ne soit transmis au modèle nouvellement créé.
Enfin, pour nous aider à créer de nouveaux modèles, Lighthouse fournit une directive de schéma @create
qui prendra les arguments que nous avons définis et créera un nouveau modèle. L'exécution de la même logique dans un contrôleur ressemblerait à ceci :
namespace App\Http\Controllers; use Illuminate\Http\Request; class UserController extends Controller { /** * Create a new user. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function store(Request $request) { $data = $this->validate($request, [ 'email' => ['email', 'unique:users'], 'password' => ['min:6'] ]); $user = \App\User::create($data); return response()->json(['user' => $user]); } }
Maintenant que notre champ de mutation createUser est configuré, allons-y et exécutons-le dans GraphQL Playground avec ce qui suit :
mutation { createUser( name:"John Doe" email:"[email protected]" password: "secret" ) { id name email } }
Nous devrions obtenir la sortie suivante :
{ "data": { "createUser": { "id": "12", "name": "John Doe", "email": "[email protected]" } } }
Authentification et autorisation GraphQL
Puisque nous devons ajouter un user_id
à nos modèles d' Article
, ce serait le moment idéal pour passer en revue l'authentification et l'autorisation dans GraphQL/Lighthouse.
Pour authentifier un utilisateur, nous devons lui fournir un api_token
, créons donc une mutation pour gérer cela et nous ajouterons la directive @field
pour pointer Lighthouse vers un résolveur personnalisé qui gérera la logique. Nous définissons le résolveur de la même manière que la définition d'un contrôleur dans Laravel à l'aide de l'argument du resolver
.
Avec la directive @field
définie ci-dessous, nous disons à Lighthouse lorsque la mutation de login
est exécutée, utilisez la méthode createToken
sur notre classe App\GraphQL\Mutations\AuthMutator
:
type Mutation { # ... login( email: String! password: String! ): String @field(resolver: "AuthMutator@resolve") }
Remarque : Vous n'avez pas besoin d'inclure l'intégralité de l'espace de noms ici. Dans le fichier de configuration lighthouse.php
, vous verrez que nous avons déjà défini l'espace de noms pour nos mutations sur App\\GraphQL\\Mutations
. Cependant, vous pouvez utiliser l'espace de noms complet si vous préférez.
Utilisons le générateur de Lighthouse pour créer la nouvelle classe mutator :
$ php artisan lighthouse:mutation AuthMutator
Ensuite, mettons à jour notre fonction de résolution comme suit :
namespace App\GraphQL\Mutations; use Illuminate\Support\Arr; use Illuminate\Support\Str; use Illuminate\Support\Facades\Auth; use GraphQL\Type\Definition\ResolveInfo; use Nuwave\Lighthouse\Support\Contracts\GraphQLContext; class AuthMutator { /** * Return a value for the field. * * @param null $rootValue Usually contains the result returned from the parent field. In this case, it is always `null`. * @param mixed[] $args The arguments that were passed into the field. * @param \Nuwave\Lighthouse\Support\Contracts\GraphQLContext $context Arbitrary data that is shared between all fields of a single query. * @param \GraphQL\Type\Definition\ResolveInfo $resolveInfo Information about the query itself, such as the execution state, the field name, path to the field from the root, and more. * @return mixed */ public function resolve($rootValue, array $args, GraphQLContext $context, ResolveInfo $resolveInfo) { $credentials = Arr::only($args, ['email', 'password']); if (Auth::once($credentials)) { $token = Str::random(60); $user = auth()->user(); $user->api_token = $token; $user->save(); return $token; } return null; } }
Maintenant que notre résolveur est configuré, testons-le et essayons d'obtenir un jeton API en utilisant la mutation suivante dans GraphQL Playground :
mutation { login(email:"[email protected]", password:"secret") }
Nous devrions nous faire renvoyer un jeton comme ceci :
{ "data": { "login": "VJCz1DCpmdvB9WatqvWbXBP2RN8geZQlrQatUnWIBJCdbAyTl3UsdOuio3VE" } }
Remarque : Assurez-vous de copier le jeton renvoyé par la mutation de connexion afin que nous puissions l'utiliser plus tard.
Ensuite, ajoutons un champ de requête qui renverra l'utilisateur authentifié pour nous assurer que notre logique fonctionne. Nous allons ajouter un champ appelé me
et utiliser la directive @auth
de Lighthouse pour renvoyer l'utilisateur actuellement authentifié. Nous définirons également l'argument guard
égal à api
puisque c'est ainsi que nous authentifierons l'utilisateur.
type Query { # ... me: User @auth(guard: "api") }
Exécutons maintenant la requête. Dans GraphQL Playground, vous pouvez définir vos en-têtes de requête en double-cliquant sur l'onglet "En-têtes HTTP" en bas. Nous ajoutons des en-têtes avec un objet JSON, donc pour ajouter un jeton de support à chaque requête, vous devez ajouter ce qui suit :
{ "Authorization": "Bearer VJCz1DCpmdvB9WatqvWbXBP2RN8geZQlrQatUnWIBJCdbAyTl3UsdOuio3VE" }
Remarque : Remplacez le jeton du porteur par le jeton que vous avez reçu lors de l'exécution de la requête de connexion .
Exécutons maintenant la requête me
:
{ me { email articles { id title } } }
Nous devrions obtenir une sortie qui ressemble à ceci :
{ "data": { "me": { "email": "[email protected]", "articles": [ { "id": "1", "title": "Rerum perspiciatis et quos occaecati exercitationem." }, { "id": "2", "title": "Placeat quia cumque laudantium optio voluptatem sed qui." }, { "id": "3", "title": "Optio voluptatem et itaque sit animi." }, { "id": "4", "title": "Excepturi in ad qui dolor ad perspiciatis adipisci." }, { "id": "5", "title": "Qui nemo blanditiis sed fugit consequatur." } ] } } }
Intergiciel
Maintenant que nous savons que notre authentification fonctionne correctement, créons notre dernière mutation pour créer un article en utilisant l'utilisateur actuellement authentifié. Nous utiliserons la directive @field
pour pointer Lighthouse vers notre résolveur et nous inclurons également une directive @middleware
pour nous assurer qu'un utilisateur est connecté.
type Mutation { # ... createArticle(title: String!, content: String!): Article @field(resolver: "ArticleMutator@create") @middleware(checks: ["auth:api"]) }
Tout d'abord, générons une classe de mutation :
$ php artisan lighthouse:mutation ArticleMutator
Ensuite, mettons à jour le mutateur avec la logique suivante :
namespace App\GraphQL\Mutations; use Nuwave\Lighthouse\Support\Contracts\GraphQLContext; class ArticleMutator { /** * Return a value for the field. * * @param null $rootValue * @param mixed[] $args * @param \Nuwave\Lighthouse\Support\Contracts\GraphQLContext $context * @return mixed */ public function create($rootValue, array $args, GraphQLContext $context) { $article = new \App\Article($args); $context->user()->articles()->save($article); return $article; } }
Remarque : nous avons renommé la fonction de resolve
par défaut en create
. Vous n'avez pas besoin de créer une nouvelle classe pour chaque résolveur. Au lieu de cela, vous pouvez regrouper la logique si cela a plus de sens.
Enfin, exécutons notre nouvelle mutation et vérifions la sortie. Assurez-vous de conserver l'en-tête d' Authorization
de notre requête précédente dans l'onglet "En-têtes HTTP" :
mutation { createArticle( title:"Building a GraphQL Server with Laravel" content:"In case you're not currently familiar with it, GraphQL is a query language used to interact with your API..." ) { id author { id email } } }
Nous devrions obtenir la sortie suivante :
{ "data": { "createArticle": { "id": "56", "author": { "id": "1", "email": "[email protected]" } } } }
Emballer
Pour récapituler, nous avons utilisé Lighthouse pour créer un serveur GraphQL pour notre projet Laravel. Nous avons utilisé certaines directives de schéma intégrées, créé des requêtes et des mutations, et géré l'autorisation et l'authentification.
Lighthouse vous permet de faire beaucoup plus (comme vous permettre de créer vos propres directives de schéma personnalisées), mais pour les besoins de cet article, nous nous sommes tenus aux bases et nous avons pu mettre en place un serveur GraphQL avec assez peu de passe-partout.
La prochaine fois que vous devrez configurer une API pour une application mobile ou d'une seule page, assurez-vous de considérer GraphQL comme un moyen d'interroger vos données !