Creazione di un server GraphQL con Laravel

Pubblicato: 2022-03-11

Nel caso in cui non hai ancora familiarità con esso, GraphQL è un linguaggio di query utilizzato per interagire con la tua API che offre alcuni vantaggi rispetto ad architetture alternative come REST. GraphQL è estremamente utile se utilizzato come endpoint per applicazioni mobili e a pagina singola. GraphQL consente di eseguire query sui dati nidificati e correlati in una richiesta con relativa facilità, consentendo agli sviluppatori di ottenere i dati esatti di cui hanno bisogno in un unico round trip al server.

Laravel è un framework Web PHP popolare e supponente. Fornisce numerosi strumenti integrati per far funzionare rapidamente le applicazioni, ma consente anche agli sviluppatori di sostituire le proprie implementazioni con le interfacce integrate di Laravel quando lo si preferisce.

Sebbene le comunità che circondano sia GraphQL che Laravel siano cresciute notevolmente da quando erano open source, la documentazione che spiega come utilizzare queste due tecnologie insieme è ancora alquanto scarsa.

Quindi, in questo tutorial, ti mostrerò come creare il tuo server GraphQL usando Laravel.

Panoramica del progetto

Illustrazione della panoramica del server GraphQL

Prima di iniziare, dovremo familiarizzare con il progetto che stiamo tentando di costruire. Per fare ciò, definiremo le nostre risorse e creeremo il nostro schema GraphQL, che utilizzeremo in seguito per servire la nostra API.

Risorse del progetto

La nostra applicazione sarà composta da due risorse: Articoli e Utenti . Queste risorse saranno definite come tipi di oggetti nel nostro schema GraphQL:

 type User { id: ID! name: String! email: String! articles: [Article!]! } type Article { id: ID! title: String! content: String! author: User! }

Osservando lo schema, possiamo vedere che abbiamo una relazione uno-a-molti tra i nostri due oggetti. Gli utenti possono scrivere molti articoli e a un articolo è assegnato un autore (utente).

Ora che abbiamo definito i nostri tipi di oggetti, avremo bisogno di un modo per creare e interrogare i nostri dati, quindi definiamo i nostri oggetti di query e mutazione:

 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 }

Allestimento del nostro progetto Laravel

Ora che abbiamo definito il nostro schema GraphQL, mettiamo in funzione il nostro progetto Laravel. Iniziamo creando un nuovo progetto Laravel via Composer:

 $ composer create-project --prefer-dist laravel/laravel laravel-graphql

Solo per assicurarci che tutto funzioni, avviamo il nostro server e assicuriamoci di vedere la pagina predefinita di Laravel:

 $ cd laravel-graphql $ php artisan serve Laravel development server started: <http://127.0.0.1:8000>

Modelli e migrazioni di database

Ai fini di questo articolo, utilizzeremo SQLite. Quindi, apportiamo le seguenti modifiche al file .env predefinito:

 DB_CONNECTION=sqlite # DB_HOST= # DB_PORT= # DB_DATABASE=database.sqlite # DB_USERNAME= # DB_PASSWORD=

Quindi, creiamo il nostro file di database:

 $ touch ./database/database.sqlite

Laravel viene fornito con un modello utente e alcuni file di migrazione di base. Aggiungiamo rapidamente una colonna api_token al nostro file di migrazione CreateUsersTable fornitoci da 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'); } }

Torneremo a questa colonna aggiuntiva più avanti nell'articolo quando arriveremo all'autorizzazione. Ora andiamo avanti e creiamo il nostro modello di articolo e un file di migrazione per creare la tabella associata:

 $ php artisan make:model Article -m

Nota: l'opzione -m crea un file di migrazione per il nostro modello di articolo appena creato.

Apportiamo alcune modifiche al file di migrazione generato:

 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'); } }

Abbiamo aggiunto una chiave esterna che punta id nella tabella users , nonché alle colonne del title e del content che abbiamo definito nel nostro schema GraphQL.

Ora che abbiamo definito i nostri file di migrazione, andiamo avanti ed eseguiamoli sul nostro database:

 $ php artisan migrate

Successivamente, aggiorniamo i nostri modelli definendo le relazioni necessarie:

 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); } }

Inseminazione del database

Ora che abbiamo configurato i nostri modelli e le migrazioni, eseguiamo il seeding del nostro database. Inizieremo creando alcune classi seeder per i nostri articles e le tabelle users :

 $ php artisan make:seeder UsersTableSeeder $ php artisan make:seeder ArticlesTableSeeder

Quindi, impostiamoli per inserire alcuni dati fittizi nel nostro database 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); } }

Infine, andiamo avanti ed eseguiamo i nostri seeders di database per ottenere alcuni dati nel nostro database:

 $ php artisan db:seed

Faro di Laravel e Server GraphQL

Ora che abbiamo impostato il nostro database e i nostri modelli, è tempo di iniziare a creare il nostro server GraphQL. Attualmente sono disponibili diverse soluzioni per Laravel, ma per questo articolo utilizzeremo Lighthouse.

Lighthouse è un pacchetto che ho creato alcuni anni fa e di recente ha ricevuto un supporto straordinario dalla crescente comunità che lo circonda. Consente agli sviluppatori di configurare rapidamente un server GraphQL utilizzando Laravel con poco standard, pur essendo sufficientemente flessibile da consentire agli sviluppatori di personalizzarlo per soddisfare le esigenze di qualsiasi progetto.

Illustrazione del faro di Laravel e del server GraphQL

Iniziamo inserendo il pacchetto nel nostro progetto:

 $ composer require nuwave/lighthouse:"3.1.*"

Successivamente, pubblichiamo il file di configurazione di Lighthouse:

 $ php artisan vendor:publish --provider="Nuwave\Lighthouse\LighthouseServiceProvider" --tag=config

Nota: puoi anche scegliere di pubblicare il file dello schema predefinito di Lighthouse semplicemente rimuovendo l'opzione --tag=config . Ma ai fini di questo articolo, creeremo il nostro file di schema da zero.

Se diamo un'occhiata al file config/lighthouse.php noterai un'impostazione utilizzata per registrare il nostro file schema con Lighthouse:

 'schema' => [ 'register' => base_path('graphql/schema.graphql'), ],

Quindi andiamo avanti e creiamo il nostro file di schema e impostiamo il nostro tipo di oggetto utente e la query:

 $ 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 }

Noterai che il nostro schema è simile a quello che abbiamo definito in precedenza, tranne per il fatto che abbiamo aggiunto alcuni identificatori chiamati direttive dello schema.

Prendiamoci un momento per scomporre il nostro schema definito. La nostra prima definizione è un tipo di oggetto chiamato User che ha una relazione con il nostro modello eloquente App\User . Abbiamo definito l' id , il name e l'e email come campi che possono essere interrogati dai nostri modelli User . In alternativa, ciò significa che le colonne password , created_at e updated_at sono campi che non possono essere richiesti dalla nostra API.

Successivamente abbiamo il nostro tipo di Query che è un punto di ingresso nella nostra API e può essere utilizzato per eseguire query sui dati. Il nostro primo campo è il campo degli users che restituisce un array di tipi di oggetti User . La direttiva @all dice a Lighthouse di eseguire una query Eloquent, utilizzando il nostro modello User e ottenere tutti i risultati. Sarebbe come eseguire quanto segue:

 $users = \App\User::all();

Nota: Lighthouse sa cercare un modello nello spazio dei nomi \App\User a causa dell'opzione spazi dei namespaces definita nel suo file di configurazione.

Il nostro secondo campo definito sul nostro tipo di query è call user , che accetta un id come argomento e restituisce un singolo tipo di oggetto User . Abbiamo anche aggiunto due direttive per aiutare Lighthouse a creare automaticamente una query per noi e restituire un singolo modello User . La direttiva @eq dice a Lighthouse di aggiungere un dove nella nostra colonna id e la direttiva @find indica a Lighthouse di restituire un singolo risultato. Per scrivere questa query utilizzando il generatore di query di Laravel, sarebbe simile a questo:

 $user = \App\User::where('id', $args['id'])->first();

Interrogazione della nostra API GraphQL

Ora che abbiamo un po' di informazioni su come Lighthouse utilizza il nostro schema per creare query, eseguiamo il nostro server e iniziamo a interrogare i dati. Inizieremo eseguendo il nostro server:

 $ php artisan serve Laravel development server started: <http://127.0.0.1:8000>

Per interrogare un endpoint GraphQL, puoi eseguire il comando cURL nel terminale o in un client standard come Postman. Tuttavia, per ottenere tutti i vantaggi di GraphQL (come il completamento automatico, l'evidenziazione degli errori, la documentazione, ecc., utilizzeremo GraphQL Playground (download di rilascio qui).

Quando avvii Playground, fai clic sulla scheda "URL Endpoint" e digita http://localhost:8000/graphql per indirizzare GraphQL Playground al nostro server. Sul lato sinistro dell'editor, possiamo interrogare i nostri dati, quindi iniziamo chiedendo a tutti gli utenti con cui abbiamo inserito il database:

 { users { id email name } }

Quando premi il pulsante di riproduzione nel mezzo dell'IDE (o fai clic su Ctrl+Invio ), vedrai l'output JSON del nostro server sul lato destro, che assomiglierà a questo:

 { "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" }, ... ] } }

Nota: poiché abbiamo utilizzato Faker per eseguire il seeding del nostro database, i dati nei campi dell'e- email e del name saranno diversi.

Ora proviamo a eseguire query per un singolo utente:

 { user(id: 1) { email name } }

E otterremo il seguente output per un singolo utente:

 { "data": { "user": { "email": "[email protected]", "name": "Carolyn Powlowski" } } }

Interrogare dati come questo è utile per iniziare, ma è altamente improbabile che ti trovi in ​​un progetto in cui vorresti mai eseguire query per tutti i tuoi dati, quindi proviamo ad aggiungere un po' di impaginazione. Quando esaminiamo l'ampia gamma di direttive integrate di Lighthouse, abbiamo una direttiva @paginate prontamente disponibile, quindi aggiorniamo l'oggetto query del nostro schema in questo modo:

 type Query { user(id: ID! @eq): User @find users: [User!]! @paginate }

Se ricarichiamo GraphQL Playground ( Ctrl/Cmd + R ) e riproviamo la query dei nostri users , noterai che viene visualizzato un messaggio di errore che indica Cannot query field "id" on type "UserPaginator" , quindi cosa è successo? Dietro le quinte, Lighthouse manipola il nostro schema per consentirci di ottenere un set impaginato di risultati e lo fa modificando il tipo di ritorno del campo dei nostri users .

Diamo un'occhiata più da vicino esaminando il nostro schema nella scheda "Documenti" di GraphQL Playground. Se dai un'occhiata al campo degli users , restituisce un UserPaginator che restituisce un array di utenti e un tipo PaginatorInfo definito da 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! }

Se hai familiarità con l'impaginazione integrata di Laravel, i campi disponibili nel tipo PaginatorInfo ti sembreranno probabilmente molto familiari. Quindi, per interrogare due utenti, ottenere il numero totale di utenti nel sistema e verificare di avere più pagine da scorrere, invieremo la seguente query:

 { users(count:2) { paginatorInfo { total hasMorePages } data { id name email } } }

Che ci fornirà la seguente risposta:

 { "data": { "users": { "paginatorInfo": { "total": 11, "hasMorePages": true }, "data": [ { "id": "1", "name": "Carolyn Powlowski", "email": "[email protected]" }, { "id": "2", "name": "Elouise Raynor", "email": "[email protected]" }, ] } } }

Relazioni

In genere, quando si sviluppa un'applicazione, la maggior parte dei dati è correlata. Nel nostro caso, un User può scrivere molti Articles , quindi aggiungiamo quella relazione al nostro tipo di utente e definiamo il nostro tipo di Article :

 type User { id: ID! name: String! email: String! articles: [Article!]! @hasMany } type Article { id: ID! title: String! content: String! }

Qui, stiamo usando un'altra direttiva dello schema fornita da Lighthouse @hasMany , che dice a Lighthouse che il nostro modello User ha una \Illuminate\Database\Eloquent\Relations\HasMany con il modello Article .

Ora interroghiamo la nostra relazione appena definita:

 { user(id:1) { articles { id title } } }

Questo ci fornirà la seguente risposta:

 { "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." } ] } } }

Infine, invertiamo la nostra relazione e aggiungiamo la nostra relazione con l' author al nostro tipo di oggetto Article utilizzando la direttiva dello schema @belongsTo di Lighthouse e aggiornando la nostra 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 }

Vedrai che abbiamo aggiunto un argomento di relation facoltativo alla direttiva @belongsTo . Questo dice a Lighthouse di utilizzare la relazione user del modello Articles e di assegnarla al campo author .

Ora interroghiamo un elenco di articoli e prendiamo il loro autore associato:

 { articles(count:2) { paginatorInfo { total hasMorePages } data { id title author { name email } } } }

E dovremmo ottenere quanto segue dal nostro server:

 { "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]" } } ] } } }

Mutazione GraphQL

Ora che possiamo interrogare i nostri dati, creiamo alcune mutazioni per creare nuovi utenti e articoli. Inizieremo con il nostro modello utente:

 type Mutation { createUser( name: String! email: String! @rules(apply: ["email", "unique:users"]) password: String! @bcrypt @rules(apply: ["min:6"]) ): User @create }

Ora analizziamo questa definizione dello schema. Abbiamo creato una mutazione chiamata createUser che accetta tre argomenti ( name , email e password ). Abbiamo applicato la direttiva @rules sia ai nostri argomenti email che password . Questo può sembrare un po' familiare perché è simile alla logica di convalida fornita da Laravel per i suoi controller.

Successivamente, abbiamo allegato la direttiva @bcrypt al nostro campo password . Questo crittograferà la password prima che venga passata al modello appena creato.

Infine, per aiutarci a creare nuovi modelli, Lighthouse fornisce una direttiva @create schema che prenderà gli argomenti che abbiamo definito e creerà un nuovo modello. L'esecuzione della stessa logica in un controller sarebbe simile alla seguente:

 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]); } }

Ora che abbiamo impostato il nostro campo di mutazione createUser, andiamo avanti ed eseguiamolo in GraphQL Playground con quanto segue:

 mutation { createUser( name:"John Doe" email:"[email protected]" password: "secret" ) { id name email } }

Dovremmo ottenere il seguente output:

 { "data": { "createUser": { "id": "12", "name": "John Doe", "email": "[email protected]" } } }

Autenticazione e autorizzazione GraphQL

Dal momento che dobbiamo aggiungere un user_id ai nostri modelli di Article , ora sarebbe un ottimo momento per esaminare l'autenticazione e l'autorizzazione in GraphQL/Lighthouse.

testo alternativo immagine

Per autenticare un utente, dobbiamo fornire loro un api_token , quindi creiamo una mutazione per gestirlo e aggiungeremo la direttiva @field per puntare Lighthouse a un risolutore personalizzato che gestirà la logica. Impostiamo il resolver nello stesso schema della definizione di un controller in Laravel usando l'argomento resolver .

Con la direttiva @field definita di seguito, stiamo dicendo a Lighthouse quando viene eseguita la mutazione di login , utilizzare il metodo createToken sulla nostra classe App\GraphQL\Mutations\AuthMutator :

 type Mutation { # ... login( email: String! password: String! ): String @field(resolver: "AuthMutator@resolve") }

Nota: non è necessario includere l'intero spazio dei nomi qui. Nel file di configurazione lighthouse.php vedrai che lo spazio dei nomi definito per le nostre mutazioni è già impostato come App\\GraphQL\\Mutations , tuttavia, puoi utilizzare lo spazio dei nomi completo se preferisci.

Usiamo il generatore di Lighthouse per creare la nuova classe mutatore:

 $ php artisan lighthouse:mutation AuthMutator

Quindi, aggiorniamo la nostra funzione di risoluzione in questo modo:

 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; } }

Ora che abbiamo impostato il nostro risolutore, proviamolo e proviamo a ottenere un token API usando la seguente mutazione in GraphQL Playground:

 mutation { login(email:"[email protected]", password:"secret") }

Dovremmo ricevere un token che ci viene restituito in questo modo:

 { "data": { "login": "VJCz1DCpmdvB9WatqvWbXBP2RN8geZQlrQatUnWIBJCdbAyTl3UsdOuio3VE" } }

Nota: assicurati di copiare il token restituito dalla mutazione di accesso in modo da poterlo utilizzare in seguito.

Successivamente, aggiungiamo un campo di query che restituirà l'utente autenticato per assicurarsi che la nostra logica funzioni. Aggiungeremo un campo chiamato me e useremo la direttiva @auth di Lighthouse per restituire l'utente attualmente autenticato. Imposteremo anche l'argomento guard uguale ad api poiché è così che autenticheremo l'utente.

 type Query { # ... me: User @auth(guard: "api") }

Ora eseguiamo la query. In GraphQL Playground, puoi impostare le intestazioni delle richieste facendo doppio clic sulla scheda "Intestazioni HTTP" in basso. Aggiungiamo intestazioni con un oggetto JSON, quindi per aggiungere un token di trasporto a ogni richiesta, dovresti aggiungere quanto segue:

 { "Authorization": "Bearer VJCz1DCpmdvB9WatqvWbXBP2RN8geZQlrQatUnWIBJCdbAyTl3UsdOuio3VE" }

Nota: sostituisci il token di trasporto con il token che hai ricevuto durante l'esecuzione della query di accesso .

Ora eseguiamo la query me :

 { me { email articles { id title } } }

Dovremmo ottenere un output simile a questo:

 { "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." } ] } } }

Middleware

Ora che sappiamo che la nostra autenticazione funziona correttamente, creiamo la nostra ultima mutazione per creare un articolo utilizzando l'utente attualmente autenticato. Useremo la direttiva @field per indirizzare Lighthouse al nostro risolutore e includeremo anche una direttiva @middleware per garantire che un utente abbia effettuato l'accesso.

 type Mutation { # ... createArticle(title: String!, content: String!): Article @field(resolver: "ArticleMutator@create") @middleware(checks: ["auth:api"]) }

Per prima cosa, generiamo una classe di mutazione:

 $ php artisan lighthouse:mutation ArticleMutator

Successivamente, aggiorniamo il mutatore con la seguente logica:

 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; } }

Nota: abbiamo rinominato la funzione di resolve predefinita per create . Non è necessario creare una nuova classe per ogni risolutore. Invece, puoi raggruppare la logica insieme se ha più senso.

Infine, eseguiamo la nostra nuova mutazione e controlliamo l'output. Assicurati di mantenere l'intestazione di Authorization dalla nostra precedente query nella scheda "Intestazioni 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 } } }

Dovremmo ottenere il seguente output:

 { "data": { "createArticle": { "id": "56", "author": { "id": "1", "email": "[email protected]" } } } }

Avvolgendo

Per ricapitolare, abbiamo sfruttato Lighthouse per creare un server GraphQL per il nostro progetto Laravel. Abbiamo utilizzato alcune direttive dello schema integrate, creato query e mutazioni e gestito l'autorizzazione e l'autenticazione.

Lighthouse ti consente di fare molto di più (come permetterti di creare le tue direttive di schema personalizzate) ma per gli scopi di questo articolo ci siamo limitati alle basi e siamo stati in grado di far funzionare un server GraphQL con una piastra abbastanza piccola.

La prossima volta che devi configurare un'API per un'applicazione mobile o a pagina singola, assicurati di considerare GraphQL come un modo per interrogare i tuoi dati!

Correlati: Autenticazione utente completa e controllo degli accessi - Un tutorial sul passaporto Laravel, pt. 1