O GraphQL tem um grande potencial na forma como os aplicativos voltados para o cliente solicitam dados, evitando o gerenciamento de grandes quantidades de cargas úteis desnecessárias e recuperando apenas o que realmente importa. Para esta postagem no blog, mostrarei como criar uma aplicação Laravel.
O que é GraphQL?
Uma Query Language. Infelizmente é uma resposta simples e pouco objetiva. Mesmo que GraphQL em si seja algo simples, por vários motivos a explicação do que ele é não é a mais simples.
Instalando e configurando dependências
Antes de tudo vamos antes configurar algumas dependências:
Criando um projeto Laravel
Vamos começar um novo projeto com o comando:
composer create-project laravel/laravel graphql-laravel
Se você não possui o composer instalado clique aqui para instalar.
Instalando o Sail
Laravel Sail é uma interface de linha de comando para interagir com o ambiente de desenvolvimento Docker padrão do Laravel. O Sail fornece um ótimo ponto de partida para criar um aplicativo Laravel usando PHP, MySQL e Redis sem exigir experiência prévia do Docker.
Em sua essência, Sail é o arquivo docker-compose.yml, o script de navegação fornece uma CLI com métodos convenientes para interagir com os contêineres do Docker definidos pelo arquivo docker-compose.yml.
Vamos instalar o Sail como uma dependência de desenvolvimento com:
composer require laravel/sail --dev
Como estamos usando o docker para executar o ambiente de desenvolvimento, precisamos de um Dockerfile, certo? Para ter acesso a este arquivo docker, e após instalar a dependência sail do comando anterior, você precisa executar o comando sail:install
.
php artisan sail:install
O comando irá perguntar qual banco de dados você irá utilizar, basta escolher uma e pressionar enter
.
E pronto, já podemos rodar nossa aplicação com o Sail utilizando o comando:
./vendor/bin/sail up -d
Para facilitar o uso do Sail e não termos de rodar o comando ./vendor/bin/sail up -d
toda vez podemos adicionar um alias para facilitar o comando, para fazer isso basta adicionar a linha abaixo no seu arquivo do bash (~/.bashrc
ou ~/.zshrc
).
alias sail='[ -f sail ] && bash sail || bash vendor/bin/sail'
E então podemos rodar o Sail com:
sail up -d
Ou pará-lo com :
sail stop
Instalando o Lighthouse
O Lighthouse é um pacote para Laravel que vai nos ajudar a criar uma API GraphQL.
Vamos começar instalando:
sail composer require nuwave/lighthouse
E publicamos o schema padrão em graphql/schema.graphql
:
sail artisan vendor:publish --tag=lighthouse-schema
E também o arquivo de configuração do Lighthouse:
sail artisan vendor:publish --tag=lighthouse-config
O arquivo será criado em config/lighthouse.php
.
Para podermos testar de forma simples vamos adicionar o GraphQL Playground.
sail composer require mll-lab/laravel-graphql-playground
Você poderá acessar o playground pelo endereço http://localhost/graphql-playground
.
Para finalizar a configuração do Lighthouse, vamos habilitar o CORS (Cross-Origin Resource Sharing) para seus endpoints GraphQL em config/cors.php
alterando a linha:
return [
- 'paths' => ['api/*', 'sanctum/csrf-cookie'],
+ 'paths' => ['api/*', 'graphql', 'sanctum/csrf-cookie'],
];
Configurando o Sanctum
O Sanctum já está instalado em nosso projeto, para conferir basta verificar se o arquivo config/sanctum.php
existe, então precisamos apenas adicioná-lo ao Lighthouse, editando config/lighthouse.php
:
return [
- 'guard' => 'api',
+ 'guard' => 'sanctum',
];
Criando a API
Agora que tudo está configurado vamos começar!
Atualizando nosso Schema
A primeira coisa que faremos é adicionar a autenticação da API para permitir que os usuários façam login em suas contas. Normalmente, ao desenvolver uma API REST, você começa definindo o endpoint da API. No GraphQL você tem apenas um endpoint que será usado para executar Queries e Mutations. Cada “endpoint” deve estar presente em nosso esquema GraphQL, então vamos começar criando nossa mutation de login.
Adicione ao arquivo graphql/schema.graphql
:
type AccessToken {
token: String!
}
input LoginInput {
email: String! @rules(apply: ["email"])
password: String!
}
extend type Mutation {
login(input: LoginInput @spread): AccessToken!
@field(resolver: "App\\GraphQL\\Mutations\\AuthMutation@login")
}
Criando a primeira mutation
Podemos ver que nossa autenticação está utilizando da mutation AuthMutation mas ainda precisamos criá-la com:
sail artisan lighthouse:mutation AuthMutation
Você deve ter um novo arquivo AuthMutation.php
em app\GraphQL\Mutations
. Essa mutation será responsável por receber o e-mail e senha e lidar com a autenticação.
namespace App\GraphQL\Mutations;
use Illuminate\Auth\AuthManager;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Nuwave\Lighthouse\Exceptions\AuthenticationException;
class AuthMutation
{
public function __construct(private AuthManager $authManager)
{
}
public function login($_, array $args)
{
$userProvider = $this->authManager->createUserProvider('users');
$user = $userProvider->retrieveByCredentials([
'email' => $args['email'],
'password' => $args['password'],
]);
if (!$user || !$userProvider->validateCredentials($user, $args)) {
throw new AuthenticationException('The provided credentials are incorrect.');
}
if ($user instanceof MustVerifyEmail && !$user->hasVerifiedEmail()) {
throw new AuthenticationException('Your email address is not verified.');
}
return [
'token' => $user->createToken('login')->plainTextToken,
];
}
}
Para podermos testar nossa autenticação vamos criar um usuário utilizando o Laravel Tinker para facilitar.
sail artisan tinker
Com o Tinker, você pode executar o código PHP diretamente do seu terminal, o que permite executar métodos de classe. Com isso dito, podemos facilmente criar um novo usuário com o UserFactory que vem com a instalação padrão do Laravel:
>>> User::factory()->create(['email' => 'email@provider.com']);
A saída deste comando deve ser uma nova instância do User::class e como chamamos o método create() os dados devem ser persistidos em nosso banco de dados.
[!] Aliasing 'User' to 'App\Models\User' for this Tinker session.
=> App\Models\User {#3626
name: "Peggie Jaskolski PhD",
email: "email@provider.com",
email_verified_at: "2022-04-17 21:29:33",
#password: "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi",
#remember_token: "HwJWfY62uG",
updated_at: "2022-04-17 21:29:34",
created_at: "2022-04-17 21:29:34",
id: 1,
}
Autenticando
Já temos nosso usuário criado, e nosso schema e metodos para autenticação prontos, com tudo isso feito, vamos finalmente tentar fazer a requisição acessando nosso playground http://localhost/graphql-playground
e executando nossa mutation:
mutation {
login(input: { email: "email@provider.com", password: "password" }) {
token
}
}
E se você seguiu o tutorial corretamente até o momento o retorno será algo como:
{
"data": {
"login": {
"token": "1|4rbAzr3tqnof5Upd12q3RaGLzMbWfIsQVL8wVtAC"
}
}
}
Verificando o token
Vamos ao último passo para ter certeza que o token gerado é realmente do usuário solicitado.
Para isso, adicionaremos uma query ao arquivo graphql/schema.graphql
:
type Query {
me: User @auth
}
E simples assim poderemos saber qual usuário está autenticado, ou recebemos um null caso nenhum ou um token inválido seja passado.
No playground basta adicionar nosso token em nosso Authorization
Header:
{
"Authorization": "Bearer 1|4rbAzr3tqnof5Upd12q3RaGLzMbWfIsQVL8wVtAC"
}
Com isso temos nossa primeira API GraphQL feita, então sinta-se à vontade para criar novas mutations e queries.
O Projeto completo pode ser baixado nesse repositório