Construyendo un servidor GraphQL con Laravel
Publicado: 2022-03-11En caso de que aún no esté familiarizado con él, GraphQL es un lenguaje de consulta que se utiliza para interactuar con su API y que brinda algunos beneficios en comparación con arquitecturas alternativas como REST. GraphQL es extremadamente útil cuando se usa como punto final para aplicaciones móviles y de una sola página. GraphQL le permite consultar datos anidados y relacionados en una solicitud con relativa facilidad, lo que permite a los desarrolladores obtener los datos exactos que necesitan en un solo viaje de ida y vuelta al servidor.
Laravel es un marco web PHP popular y obstinado. Proporciona numerosas herramientas integradas para que las aplicaciones funcionen rápidamente, pero también permite a los desarrolladores cambiar sus propias implementaciones por las interfaces integradas de Laravel cuando lo prefieran.
Aunque las comunidades que rodean a GraphQL y Laravel han crecido de manera espectacular desde que eran de código abierto, la documentación que explica cómo usar estas dos tecnologías juntas todavía es algo escasa.
Entonces, en este tutorial, te mostraré cómo crear tu propio servidor GraphQL usando Laravel.
Descripción del proyecto
Antes de comenzar, debemos familiarizarnos con el proyecto que estamos intentando construir. Para hacer eso, definiremos nuestros recursos y crearemos nuestro esquema GraphQL, que luego usaremos para servir nuestra API.
Recursos del proyecto
Nuestra aplicación constará de dos recursos: Artículos y Usuarios . Estos recursos se definirán como tipos de objetos en nuestro esquema GraphQL:
type User { id: ID! name: String! email: String! articles: [Article!]! } type Article { id: ID! title: String! content: String! author: User! }
Mirando el esquema, podemos ver que tenemos una relación de uno a muchos entre nuestros dos objetos. Los usuarios pueden escribir muchos artículos y un artículo tiene un autor (usuario) asignado.
Ahora que tenemos nuestros tipos de objetos definidos, necesitaremos una forma de crear y consultar nuestros datos, así que definamos nuestros objetos de consulta y mutación:
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 nuestro proyecto Laravel
Ahora que hemos definido nuestro esquema GraphQL, pongamos en marcha nuestro proyecto Laravel. Comencemos creando un nuevo proyecto Laravel a través de Composer:
$ composer create-project --prefer-dist laravel/laravel laravel-graphql
Solo para asegurarnos de que todo funcione, iniciemos nuestro servidor y asegurémonos de ver la página predeterminada de Laravel:
$ cd laravel-graphql $ php artisan serve Laravel development server started: <http://127.0.0.1:8000>
Modelos de bases de datos y migraciones
A los efectos de este artículo, utilizaremos SQLite. Entonces, hagamos los siguientes cambios en el archivo .env
predeterminado:
DB_CONNECTION=sqlite # DB_HOST= # DB_PORT= # DB_DATABASE=database.sqlite # DB_USERNAME= # DB_PASSWORD=
A continuación, vamos a crear nuestro archivo de base de datos:
$ touch ./database/database.sqlite
Laravel se envía con un modelo de usuario y algunos archivos de migración básicos. Agreguemos rápidamente una columna api_token
en nuestro archivo de migración CreateUsersTable
que nos proporcionó 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'); } }
Volveremos a esta columna adicional más adelante en el artículo cuando lleguemos a la autorización. Ahora sigamos adelante y creemos nuestro modelo de artículo y un archivo de migración para crear la tabla asociada:
$ php artisan make:model Article -m
Nota: La opción -m crea un archivo de migración para nuestro modelo de artículo recién creado.
Hagamos algunos ajustes al archivo de migración generado:
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'); } }
Agregamos una clave externa que apunta a la id
en nuestra tabla de users
, así como las columnas de title
y content
que definimos en nuestro esquema GraphQL.
Ahora que tenemos nuestros archivos de migración definidos, avancemos y ejecútelos en nuestra base de datos:
$ php artisan migrate
A continuación, actualicemos nuestros modelos definiendo las relaciones necesarias:
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); } }
Siembra de base de datos
Ahora que tenemos configurados nuestros modelos y migraciones, sembraremos nuestra base de datos. Comenzaremos creando algunas clases seeder para nuestras tablas de articles
y users
:
$ php artisan make:seeder UsersTableSeeder $ php artisan make:seeder ArticlesTableSeeder
A continuación, configurémoslos para insertar algunos datos ficticios en nuestra base de datos 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, avancemos y ejecutemos nuestros sembradores de bases de datos para obtener algunos datos en nuestra base de datos:
$ php artisan db:seed
Faro de Laravel y servidor GraphQL
Ahora que tenemos nuestra base de datos y modelos configurados, es hora de comenzar a construir nuestro servidor GraphQL. Actualmente, hay varias soluciones disponibles para Laravel, pero para este artículo, usaremos Lighthouse.
Lighthouse es un paquete que creé hace unos años y recientemente ha recibido un apoyo increíble de la creciente comunidad que lo rodea. Permite a los desarrolladores configurar rápidamente un servidor GraphQL usando Laravel con poco repetitivo y, al mismo tiempo, es lo suficientemente flexible como para permitir que los desarrolladores lo personalicen para satisfacer las necesidades de casi cualquier proyecto.
Comencemos introduciendo el paquete en nuestro proyecto:
$ composer require nuwave/lighthouse:"3.1.*"
A continuación, publiquemos el archivo de configuración de Lighthouse:
$ php artisan vendor:publish --provider="Nuwave\Lighthouse\LighthouseServiceProvider" --tag=config
Nota: también puede optar por publicar el archivo de esquema predeterminado de Lighthouse simplemente eliminando la opción --tag=config
. Pero para los propósitos de este artículo, vamos a crear nuestro archivo de esquema desde cero.
Si echamos un vistazo al archivo config/lighthouse.php
, notará una configuración utilizada para registrar nuestro archivo de esquema con Lighthouse:
'schema' => [ 'register' => base_path('graphql/schema.graphql'), ],
Así que sigamos adelante y creemos nuestro archivo de esquema y configuremos nuestro tipo de objeto de usuario y 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 }
Notará que nuestro esquema se parece al que definimos anteriormente, excepto que hemos agregado algunos identificadores llamados directivas de esquema.
Tomemos un momento para desglosar nuestro esquema definido. Nuestra primera definición es un tipo de objeto llamado User
que tiene una relación con nuestro modelo elocuente App\User
. Definimos el id
, el name
y el email
como campos que se pueden consultar en nuestros modelos de User
. Alternativamente, esto significa que las columnas password
, created_at
y updated_at
son campos que no se pueden consultar desde nuestra API.
A continuación, tenemos nuestro tipo de Query
, que es un punto de entrada a nuestra API y se puede utilizar para consultar datos. Nuestro primer campo es el campo de users
que devuelve una matriz de tipos de objetos de User
. La directiva @all
le dice a Lighthouse que ejecute una consulta Eloquent, usando nuestro modelo User
y obtenga todos los resultados. Esto sería lo mismo que ejecutar lo siguiente:
$users = \App\User::all();
Nota: Lighthouse sabe buscar un modelo en el espacio de nombres \App\User
debido a la opción de namespaces
de nombres definida en su archivo de configuración.
Nuestro segundo campo definido en nuestro tipo de consulta es el user
de llamada, que toma una id
como argumento y devuelve un solo tipo de objeto User
. También agregamos dos directivas para ayudar a Lighthouse a crear automáticamente una consulta para nosotros y devolver un único modelo User
. La directiva @eq
le dice a Lighthouse que agregue un lugar en nuestra columna de id
, y la directiva @find
le indica a Lighthouse que devuelva un solo resultado. Para escribir esta consulta usando el generador de consultas de Laravel, se vería así:
$user = \App\User::where('id', $args['id'])->first();
Consultando nuestra API GraphQL
Ahora que tenemos una idea de cómo Lighthouse usa nuestro esquema para crear consultas, ejecutemos nuestro servidor y comencemos a consultar datos. Comenzaremos ejecutando nuestro servidor:
$ php artisan serve Laravel development server started: <http://127.0.0.1:8000>
Para consultar un punto final de GraphQL, puede ejecutar el comando cURL en la terminal o en un cliente estándar como Postman. Sin embargo, para obtener todos los beneficios de GraphQL (como autocompletado, resaltado de errores, documentación, etc.), usaremos GraphQL Playground (descargas de lanzamiento aquí).
Al iniciar Playground, haga clic en la pestaña "Punto final de URL" y escriba http://localhost:8000/graphql para apuntar GraphQL Playground a nuestro servidor. En el lado izquierdo del editor, podemos consultar nuestros datos, así que comencemos preguntando por todos los usuarios con los que sembramos la base de datos:
{ users { id email name } }
Cuando presione el botón de reproducción en el medio del IDE (o haga clic en Ctrl+Enter ), verá la salida JSON de nuestro servidor en el lado derecho, que se verá así:
{ "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: debido a que usamos Faker para sembrar nuestra base de datos, los datos en los campos de email
y name
serán diferentes.
Ahora intentemos consultar para un solo usuario:
{ user(id: 1) { email name } }
Y obtendremos el siguiente resultado para un solo usuario:
{ "data": { "user": { "email": "[email protected]", "name": "Carolyn Powlowski" } } }
Consultar datos como este es bueno para comenzar, pero es muy poco probable que esté en un proyecto en el que alguna vez desee consultar todos sus datos, así que intentemos agregar algo de paginación. Al mirar a través de la amplia gama de directivas integradas de Lighthouse, tenemos una directiva @paginate
disponible para nosotros, así que actualicemos el objeto de consulta de nuestro esquema de la siguiente manera:
type Query { user(id: ID! @eq): User @find users: [User!]! @paginate }
Si recargamos GraphQL Playground ( Ctrl/Cmd + R ) e intentamos que nuestros users
consulten nuevamente, notará que recibimos un mensaje de error que indica Cannot query field "id" on type "UserPaginator"
, entonces, ¿qué sucedió? Detrás de escena, Lighthouse manipula nuestro esquema para que obtengamos un conjunto de resultados paginados y lo hace cambiando el tipo de retorno de nuestro campo de users
.

Echemos un vistazo más de cerca al inspeccionar nuestro esquema en la pestaña "Documentos" de GraphQL Playground. Si observa el campo de users
, está devolviendo un UserPaginator
que devuelve una matriz de usuarios y un tipo PaginatorInfo
definido por 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 está familiarizado con la paginación integrada de Laravel, los campos disponibles en el tipo PaginatorInfo
probablemente le resultarán muy familiares. Entonces, para consultar por dos usuarios, obtener el número total de usuarios en el sistema y verificar que tenemos más páginas para recorrer, enviaríamos la siguiente consulta:
{ users(count:2) { paginatorInfo { total hasMorePages } data { id name email } } }
Lo que nos proporcionará la siguiente respuesta:
{ "data": { "users": { "paginatorInfo": { "total": 11, "hasMorePages": true }, "data": [ { "id": "1", "name": "Carolyn Powlowski", "email": "[email protected]" }, { "id": "2", "name": "Elouise Raynor", "email": "[email protected]" }, ] } } }
Relaciones
Generalmente, al desarrollar una aplicación, gran parte de sus datos están relacionados. En nuestro caso, un User
puede escribir muchos Articles
, así que agreguemos esa relación a nuestro tipo de Usuario y definamos nuestro tipo de Article
:
type User { id: ID! name: String! email: String! articles: [Article!]! @hasMany } type Article { id: ID! title: String! content: String! }
Aquí, estamos usando otra directiva de esquema proporcionada por Lighthouse @hasMany
, que le dice a Lighthouse que nuestro modelo User
tiene una relación \Illuminate\Database\Eloquent\Relations\HasMany
con el modelo de Article
.
Ahora vamos a consultar nuestra relación recién definida:
{ user(id:1) { articles { id title } } }
Esto nos proporcionará la siguiente respuesta:
{ "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." } ] } } }
Finalmente, invirtamos nuestra relación y agreguemos nuestra relación de author
a nuestro tipo de objeto Article
utilizando la directiva de esquema @belongsTo
de Lighthouse y actualizando nuestra 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 }
Verá que agregamos un argumento de relation
opcional a la directiva @belongsTo
. Esto le dice a Lighthouse que use la relación de user
del modelo de Articles
y la asigne al campo de author
.
Ahora busquemos una lista de artículos y tomemos su autor asociado:
{ articles(count:2) { paginatorInfo { total hasMorePages } data { id title author { name email } } } }
Y deberíamos obtener lo siguiente de nuestro 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]" } } ] } } }
Mutación GraphQL
Ahora que podemos consultar nuestros datos, creemos algunas mutaciones para crear nuevos usuarios y artículos. Comenzaremos con nuestro modelo de usuario:
type Mutation { createUser( name: String! email: String! @rules(apply: ["email", "unique:users"]) password: String! @bcrypt @rules(apply: ["min:6"]) ): User @create }
Ahora analicemos esta definición de esquema. Hemos creado una mutación llamada createUser
que toma tres argumentos ( name
, email
y password
). Hemos aplicado la directiva @rules
a nuestros argumentos de email
y password
. Esto puede parecer un poco familiar porque es similar a la lógica de validación que proporciona Laravel para sus controladores.
A continuación, adjuntamos la directiva @bcrypt
a nuestro campo de password
. Esto cifrará la contraseña antes de que se pase al modelo recién creado.
Finalmente, para ayudarnos a crear nuevos modelos, Lighthouse proporciona una directiva @create
schema que tomará los argumentos que definimos y creará un nuevo modelo. Realizar la misma lógica en un controlador se vería así:
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]); } }
Ahora que tenemos nuestro campo de mutación createUser configurado, avancemos y ejecútelo en GraphQL Playground con lo siguiente:
mutation { createUser( name:"John Doe" email:"[email protected]" password: "secret" ) { id name email } }
Deberíamos obtener el siguiente resultado:
{ "data": { "createUser": { "id": "12", "name": "John Doe", "email": "[email protected]" } } }
Autenticación y autorización de GraphQL
Dado que necesitamos agregar un user_id
de usuario a nuestros modelos de Article
, ahora sería un buen momento para repasar la autenticación y la autorización en GraphQL/Lighthouse.
Para autenticar a un usuario, debemos proporcionarle un api_token
, así que creemos una mutación para manejar eso y agregaremos la directiva @field
para apuntar a Lighthouse a un solucionador personalizado que manejará la lógica. Configuramos el resolver en el mismo patrón que definimos un controlador en Laravel usando el argumento resolver
.
Con la directiva @field
definida a continuación, le indicamos a Lighthouse cuando se ejecuta la mutación de login
de sesión, use el método createToken
en nuestra clase App\GraphQL\Mutations\AuthMutator
:
type Mutation { # ... login( email: String! password: String! ): String @field(resolver: "AuthMutator@resolve") }
Nota: No es necesario que incluya aquí todo el espacio de nombres. En el archivo de configuración lighthouse.php
, verá que tenemos el espacio de nombres definido para nuestras mutaciones establecido como App\\GraphQL\\Mutations
; sin embargo, puede usar el espacio de nombres completo si lo prefiere.
Usemos el generador de Lighthouse para crear la nueva clase de mutantes:
$ php artisan lighthouse:mutation AuthMutator
A continuación, actualicemos nuestra función de resolución así:
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; } }
Ahora que tenemos nuestro solucionador configurado, probémoslo e intentemos obtener un token API usando la siguiente mutación en GraphQL Playground:
mutation { login(email:"[email protected]", password:"secret") }
Deberíamos recibir un token de vuelta así:
{ "data": { "login": "VJCz1DCpmdvB9WatqvWbXBP2RN8geZQlrQatUnWIBJCdbAyTl3UsdOuio3VE" } }
Nota: asegúrese de copiar el token devuelto por la mutación de inicio de sesión para que podamos usarlo más tarde.
A continuación, agreguemos un campo de consulta que devolverá el usuario autenticado para asegurarnos de que nuestra lógica funcione. Agregaremos un campo llamado me
y usaremos la directiva @auth
de Lighthouse para devolver el usuario autenticado actualmente. También estableceremos el argumento guard
igual a api
ya que así es como autenticaremos al usuario.
type Query { # ... me: User @auth(guard: "api") }
Ahora vamos a ejecutar la consulta. En GraphQL Playground, puede configurar los encabezados de su solicitud haciendo doble clic en la pestaña "Encabezados Http" en la parte inferior. Agregamos encabezados con un objeto JSON, por lo que para agregar un token de portador a cada solicitud, debe agregar lo siguiente:
{ "Authorization": "Bearer VJCz1DCpmdvB9WatqvWbXBP2RN8geZQlrQatUnWIBJCdbAyTl3UsdOuio3VE" }
Nota: Reemplace el token de portador con el token que recibió al ejecutar la consulta de inicio de sesión.
Ahora vamos a ejecutar la consulta me
:
{ me { email articles { id title } } }
Deberíamos obtener una salida que se vea así:
{ "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." } ] } } }
software intermedio
Ahora que sabemos que nuestra autenticación funciona correctamente, creemos nuestra última mutación para crear un artículo usando el usuario actualmente autenticado. Usaremos la directiva @field
para apuntar Lighthouse a nuestro resolutor y también incluiremos una directiva @middleware
para garantizar que un usuario haya iniciado sesión.
type Mutation { # ... createArticle(title: String!, content: String!): Article @field(resolver: "ArticleMutator@create") @middleware(checks: ["auth:api"]) }
Primero, generemos una clase de mutación:
$ php artisan lighthouse:mutation ArticleMutator
A continuación, actualicemos el mutador con la siguiente 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; } }
Nota: Cambiamos el nombre de la función de resolve
predeterminada para create
. No necesita crear una nueva clase para cada resolución. En su lugar, puede agrupar la lógica si tiene más sentido.
Finalmente, ejecutemos nuestra nueva mutación y verifiquemos el resultado. Asegúrese de mantener el encabezado de Authorization
de nuestra consulta anterior en la pestaña "Encabezados 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 } } }
Deberíamos obtener el siguiente resultado:
{ "data": { "createArticle": { "id": "56", "author": { "id": "1", "email": "[email protected]" } } } }
Terminando
En resumen, aprovechamos Lighthouse para crear un servidor GraphQL para nuestro proyecto Laravel. Hicimos uso de algunas directivas de esquema incorporadas, creamos consultas y mutaciones, y manejamos la autorización y la autenticación.
Lighthouse le permite hacer mucho más (como permitirle crear sus propias directivas de esquema personalizadas), pero para los fines de este artículo nos ceñimos a lo básico y pudimos poner en funcionamiento un servidor GraphQL con bastante poco repetitivo.
La próxima vez que necesite configurar una API para una aplicación móvil o de una sola página, ¡asegúrese de considerar GraphQL como una forma de consultar sus datos!