Construindo um servidor GraphQL com Laravel

Publicados: 2022-03-11

Caso você ainda não esteja familiarizado com ela, GraphQL é uma linguagem de consulta usada para interagir com sua API que oferece alguns benefícios em relação a arquiteturas alternativas como REST. O GraphQL é extremamente útil quando usado como ponto de extremidade para aplicativos móveis e de página única. O GraphQL permite consultar dados aninhados e relacionados em uma solicitação com relativa facilidade, permitindo que os desenvolvedores obtenham os dados exatos de que precisam em uma única viagem de ida e volta ao servidor.

Laravel é um framework web PHP popular e opinativo. Ele fornece várias ferramentas internas para colocar os aplicativos em funcionamento rapidamente, mas também permite que os desenvolvedores troquem suas próprias implementações pelas interfaces internas do Laravel quando preferirem.

Embora as comunidades ao redor do GraphQL e do Laravel tenham crescido dramaticamente desde que foram de código aberto, a documentação explicando como usar essas duas tecnologias juntas ainda é um pouco escassa.

Então, neste tutorial, mostrarei como criar seu próprio servidor GraphQL usando Laravel.

Visão Geral do Projeto

Ilustração de visão geral do servidor GraphQL

Antes de começarmos, precisaremos nos familiarizar com o projeto que estamos tentando construir. Para isso, definiremos nossos recursos e criaremos nosso esquema GraphQL, que usaremos posteriormente para servir nossa API.

Recursos do projeto

Nosso aplicativo será composto por dois recursos: Artigos e Usuários . Esses recursos serão definidos como tipos de objeto em nosso esquema GraphQL:

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

Observando o esquema, podemos ver que temos um relacionamento um-para-muitos entre nossos dois objetos. Os usuários podem escrever muitos artigos e um artigo tem um autor (usuário) atribuído a ele.

Agora que temos nossos tipos de objetos definidos, precisaremos de uma maneira de criar e consultar nossos dados, então vamos definir nossos objetos de consulta e mutação:

 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 }

Configurando nosso projeto Laravel

Agora que definimos nosso esquema GraphQL, vamos colocar nosso projeto Laravel em funcionamento. Vamos começar criando um novo projeto Laravel via Composer:

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

Apenas para ter certeza de que tudo está funcionando, vamos inicializar nosso servidor e ver a página padrão do Laravel:

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

Modelos de banco de dados e migrações

Para os propósitos deste artigo, usaremos o SQLite. Então, vamos fazer as seguintes alterações no arquivo .env padrão:

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

Em seguida, vamos criar nosso arquivo de banco de dados:

 $ touch ./database/database.sqlite

O Laravel vem com um modelo de usuário e alguns arquivos básicos de migração. Vamos adicionar rapidamente uma coluna api_token ao nosso arquivo de migração CreateUsersTable fornecido a nós pelo 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'); } }

Voltaremos a esta coluna adicional mais adiante no artigo, quando chegarmos à autorização. Agora vamos em frente e criar nosso modelo de artigo e um arquivo de migração para criar a tabela associada:

 $ php artisan make:model Article -m

Nota: A opção -m cria um arquivo de migração para nosso modelo de artigo recém-criado.

Vamos fazer alguns ajustes no arquivo de migração gerado:

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

Adicionamos uma chave estrangeira apontando para o id em nossa tabela de users , bem como as colunas de title e content que definimos em nosso esquema GraphQL.

Agora que temos nossos arquivos de migração definidos, vamos em frente e executá-los em nosso banco de dados:

 $ php artisan migrate

Em seguida, vamos atualizar nossos modelos definindo os relacionamentos necessários:

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

Semeadura do banco de dados

Agora que temos nossos modelos e migrações configurados, vamos semear nosso banco de dados. Começaremos criando algumas classes de seeder para nossas tabelas de articles e users :

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

Em seguida, vamos configurá-los para inserir alguns dados fictícios em nosso banco de dados 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); } }

Finalmente, vamos executar nossos seeders de banco de dados para obter alguns dados em nosso banco de dados:

 $ php artisan db:seed

Laravel Lighthouse e servidor GraphQL

Agora que temos nosso banco de dados e modelos configurados, é hora de começar a construir nosso servidor GraphQL. Atualmente, existem várias soluções disponíveis para o Laravel, mas para este artigo, usaremos o Lighthouse.

Lighthouse é um pacote que criei há alguns anos e recentemente recebeu um apoio incrível da crescente comunidade ao seu redor. Ele permite que os desenvolvedores configurem rapidamente um servidor GraphQL usando Laravel com pouco clichê, além de ser flexível o suficiente para permitir que os desenvolvedores o personalizem para atender às necessidades de praticamente qualquer projeto.

Ilustração Laravel Lighthouse e GraphQL Server

Vamos começar puxando o pacote para o nosso projeto:

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

Em seguida, vamos publicar o arquivo de configuração do Lighthouse:

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

Observação: você também pode optar por publicar o arquivo de esquema padrão do Lighthouse simplesmente removendo a opção --tag=config . Mas para os propósitos deste artigo, vamos criar nosso arquivo de esquema do zero.

Se dermos uma olhada no arquivo config/lighthouse.php você notará uma configuração usada para registrar nosso arquivo de esquema com o Lighthouse:

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

Então vamos em frente e criar nosso arquivo de esquema e configurar nosso tipo de objeto de usuário e consulta:

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

Você notará que nosso esquema é semelhante ao que definimos anteriormente, exceto que adicionamos alguns identificadores chamados diretivas de esquema.

Vamos separar um momento para detalhar nosso esquema definido. Nossa primeira definição é um tipo de objeto chamado User que tem uma relação com nosso modelo eloquente App\User . Definimos o id , name e email como campos que podem ser consultados em nossos modelos de User . Alternativamente, isso significa que as colunas password , created_at e updated_at são campos que não podem ser consultados em nossa API.

Em seguida, temos nosso tipo de Query , que é um ponto de entrada em nossa API e pode ser usado para consultar dados. Nosso primeiro campo é o campo users que retorna um array de tipos de objetos User . A diretiva @all diz ao Lighthouse para executar uma consulta Eloquent, usando nosso modelo User e obter todos os resultados. Isso seria o mesmo que executar o seguinte:

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

Nota: O Lighthouse sabe procurar um modelo no namespace \App\User por causa da opção namespaces definida em seu arquivo de configuração.

Nosso segundo campo definido em nosso tipo de consulta é a chamada user , que recebe um id como argumento e retorna um único tipo de objeto User . Também adicionamos duas diretivas para ajudar o Lighthouse a criar automaticamente uma consulta para nós e retornar um único modelo de User . A diretiva @eq diz ao Lighthouse para adicionar um where em nossa coluna id , e a diretiva @find instrui o Lighthouse a retornar um único resultado. Para escrever esta consulta usando o construtor de consultas do Laravel, ficaria assim:

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

Consultando nossa API GraphQL

Agora que temos uma ideia de como o Lighthouse usa nosso esquema para criar consultas, vamos executar nosso servidor e começar a consultar os dados. Vamos começar executando nosso servidor:

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

Para consultar um endpoint GraphQL, você pode executar o comando cURL no terminal ou em um cliente padrão, como o Postman. No entanto, para obter todos os benefícios do GraphQL (como preenchimento automático, realce de erros, documentação etc., usaremos o GraphQL Playground (downloads da versão aqui).

Ao iniciar o Playground, clique na aba “URL Endpoint” e digite http://localhost:8000/graphql para apontar o GraphQL Playground para o nosso servidor. No lado esquerdo do editor, podemos consultar nossos dados, então vamos começar perguntando por todos os usuários com os quais semeamos o banco de dados:

 { users { id email name } }

Quando você apertar o botão play no meio do IDE (ou clicar em Ctrl+Enter ), você verá a saída JSON do nosso servidor no lado direito, que será algo assim:

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

Observação: como usamos o Faker para propagar nosso banco de dados, os dados nos campos de e- email e name serão diferentes.

Agora vamos tentar consultar um único usuário:

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

E obteremos a seguinte saída para um único usuário:

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

Consultar dados como esse é bom para começar, mas é altamente improvável que você esteja em um projeto em que gostaria de consultar todos os seus dados, então vamos tentar adicionar alguma paginação. Ao examinar a ampla variedade de diretivas integradas do Lighthouse, temos uma diretiva @paginate prontamente disponível para nós, então vamos atualizar o objeto de consulta do nosso esquema da seguinte forma:

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

Se recarregarmos o GraphQL Playground ( Ctrl/Cmd + R ) e tentarmos a consulta de nossos users novamente, você notará que recebemos uma mensagem de erro informando Cannot query field "id" on type "UserPaginator" , então o que aconteceu? Nos bastidores, o Lighthouse manipula nosso esquema para obtermos um conjunto paginado de resultados e o faz alterando o tipo de retorno do nosso campo de users .

Vamos dar uma olhada mais de perto inspecionando nosso esquema na guia "Documentos" do GraphQL Playground. Se você der uma olhada no campo de users , ele está retornando um UserPaginator que retorna uma matriz de usuários e um tipo de PaginatorInfo definido pelo 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 você estiver familiarizado com a paginação interna do Laravel, os campos disponíveis no tipo PaginatorInfo provavelmente parecerão muito familiares para você. Portanto, para consultar dois usuários, obter o número total de usuários no sistema e verificar se temos mais páginas para percorrer, enviaríamos a seguinte consulta:

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

O que nos fornecerá a seguinte resposta:

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

Relacionamentos

Geralmente, ao desenvolver um aplicativo, muitos dos seus dados estão relacionados. No nosso caso, um User pode escrever muitos Articles , então vamos adicionar esse relacionamento ao nosso tipo de usuário e definir nosso tipo de Article :

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

Aqui, estamos usando outra diretiva de esquema fornecida pelo Lighthouse @hasMany , que informa ao Lighthouse que nosso modelo User tem um \Illuminate\Database\Eloquent\Relations\HasMany com o modelo Article .

Agora vamos consultar nosso relacionamento recém-definido:

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

Isso nos fornecerá a seguinte resposta:

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

Por fim, vamos reverter nosso relacionamento e adicionar nosso relacionamento de author ao nosso tipo de objeto Article usando a diretiva de esquema @belongsTo do Lighthouse, além de atualizar nossa 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 }

Você verá que adicionamos um argumento de relation opcional à diretiva @belongsTo . Isso informa ao Lighthouse para usar o relacionamento de user do modelo Articles e atribuí-lo ao campo de author .

Agora vamos consultar uma lista de artigos e pegar seu autor associado:

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

E devemos obter o seguinte do nosso servidor:

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

Mutação GraphQL

Agora que podemos consultar nossos dados, vamos criar algumas mutações para criar alguns novos usuários e artigos. Começaremos com nosso modelo de usuário:

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

Agora vamos quebrar essa definição de esquema. Criamos uma mutação chamada createUser que recebe três argumentos ( name , email e password ). Aplicamos a diretiva @rules aos nossos argumentos de email e password . Isso pode parecer um pouco familiar porque é semelhante à lógica de validação que o Laravel fornece para seus controladores.

Em seguida, anexamos a diretiva @bcrypt ao nosso campo de password . Isso criptografará a senha antes que ela seja passada para o modelo recém-criado.

Por fim, para nos ajudar a criar novos modelos, o Lighthouse fornece uma diretiva de esquema @create que pegará os argumentos que definimos e criará um novo modelo. Executar a mesma lógica em um Controller ficaria assim:

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

Agora que temos nosso campo de mutação createUser configurado, vamos em frente e executá-lo no GraphQL Playground com o seguinte:

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

Devemos obter a seguinte saída:

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

Autenticação e autorização do GraphQL

Como precisamos adicionar um user_id aos nossos modelos de Article , agora seria um ótimo momento para revisar a autenticação e a autorização no GraphQL/Lighthouse.

texto alternativo da imagem

Para autenticar um usuário, precisamos fornecer a ele um api_token , então vamos criar uma mutação para lidar com isso e adicionaremos a diretiva @field para apontar o Lighthouse para um resolvedor personalizado que manipulará a lógica. Definimos o resolvedor no mesmo padrão que definimos um controlador no Laravel usando o argumento do resolver .

Com a diretiva @field definida abaixo, informaremos ao Lighthouse quando a mutação de login for executada, use o método createToken em nossa classe App\GraphQL\Mutations\AuthMutator :

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

Observação: você não precisa incluir todo o namespace aqui. No arquivo de configuração lighthouse.php você verá que já temos o namespace definido para nossas mutações como App\\GraphQL\\Mutations —no entanto, você pode usar o namespace completo se preferir.

Vamos usar o gerador do Lighthouse para criar a nova classe mutator:

 $ php artisan lighthouse:mutation AuthMutator

Em seguida, vamos atualizar nossa função de resolvedor assim:

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

Agora que temos nosso resolvedor configurado, vamos testá-lo e tentar obter um token de API usando a seguinte mutação no GraphQL Playground:

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

Devemos receber um token enviado de volta para nós assim:

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

Observação: certifique-se de copiar o token retornado da mutação de login para que possamos usá-lo mais tarde.

Em seguida, vamos adicionar um campo de consulta que retornará o usuário autenticado para garantir que nossa lógica funcione. Adicionaremos um campo chamado me e usaremos a diretiva @auth do Lighthouse para retornar o usuário autenticado no momento. Também definiremos o argumento guard igual a api , pois é assim que autenticaremos o usuário.

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

Agora vamos executar a consulta. No GraphQL Playground, você pode definir os cabeçalhos de sua solicitação clicando duas vezes na guia “Http Headers” na parte inferior. Adicionamos cabeçalhos com um objeto JSON, portanto, para adicionar um token de portador a cada solicitação, você adicionaria o seguinte:

 { "Authorization": "Bearer VJCz1DCpmdvB9WatqvWbXBP2RN8geZQlrQatUnWIBJCdbAyTl3UsdOuio3VE" }

Observação: substitua o token do portador pelo token que você recebeu ao executar a consulta de login .

Agora vamos executar a consulta me :

 { me { email articles { id title } } }

Devemos obter uma saída que se parece com isso:

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

Agora que sabemos que nossa autenticação está funcionando corretamente, vamos criar nossa última mutação para criar um artigo usando o usuário atualmente autenticado. Usaremos a diretiva @field para apontar o Lighthouse para nosso resolvedor e também incluiremos uma diretiva @middleware para garantir que um usuário esteja conectado.

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

Primeiro, vamos gerar uma classe de mutação:

 $ php artisan lighthouse:mutation ArticleMutator

Em seguida, vamos atualizar o modificador com a seguinte lógica:

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

Observação: renomeamos a função de resolve padrão para create . Você não precisa criar uma nova classe para cada resolvedor. Em vez disso, você pode agrupar a lógica se fizer mais sentido.

Finalmente, vamos executar nossa nova mutação e verificar a saída. Certifique-se de manter o cabeçalho Authorization de nossa consulta anterior na guia “HTTP Headers”:

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

Devemos obter a seguinte saída:

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

Empacotando

Para recapitular, aproveitamos o Lighthouse para criar um servidor GraphQL para nosso projeto Laravel. Usamos algumas diretivas de esquema incorporadas, criamos consultas e mutações e tratamos de autorização e autenticação.

O Lighthouse permite que você faça muito mais (como permitir que você crie suas próprias diretivas de esquema personalizadas), mas para os propósitos deste artigo, nos apegamos ao básico e conseguimos colocar um servidor GraphQL em funcionamento com bastante pouco padrão.

Da próxima vez que você precisar configurar uma API para um aplicativo móvel ou de página única, considere o GraphQL como uma forma de consultar seus dados!

Relacionado: Autenticação completa do usuário e controle de acesso – Um tutorial do Laravel Passport, Pt. 1