Introdução ao GraphQL no Laravel

Introdução ao GraphQL no Laravel

 – 8 DE JUNHO DE 2018

Desde que foi lançado publicamente em 2015 pelo Facebook, empresas como o GitHub e o Pinterest começaram a usar o GraphQL em produção. O GraphQL introduz muitos aprimoramentos sobre o REST. Existe esse equívoco de que o GraphQL é todo sobre JavaScript. Muitas linguagens de programação diferentes suportam o GraphQL. Portanto, neste tutorial, ajudarei a corrigir esse equívoco, mostrando-lhe como começar a usar o GraphQL no Laravel.

Pré-requisitos

Este tutorial pressupõe o seguinte:

  • Conhecimento básico do GraphQL
  • Conhecimento básico do Laravel

Além disso, verifique se você tem o seguinte instalado:

  • PHP
  • SQLite
  • Compositor
  • Instalador do Laravel

O que nós estaremos construindo

Nós estaremos usando o conceito de uma lista de tarefas.

Crie um novo aplicativo Laravel

Vamos começar criando um novo projeto do Laravel. Eu vou estar usando o instalador do Laravel:

    $ laravel new laravel-graphql-tasks

Para usar o GraphQL é o nosso aplicativo Laravel, estaremos fazendo uso de um pacote chamado laravel-graphql . Vamos instalar o pacote:

    $ cd laravel-graphql-tasks
    $ composer require folklore/graphql

Nota: O restante do tutorial assume que você já está no laravel-graphql-tasksdiretório

Uma vez feita a instalação, vamos executar o comando abaixo:

    $ php artisan vendor:publish --provider="Folklore\GraphQL\ServiceProvider"

Isso criará dois novos arquivos: o config/graphql.phpque é o arquivo de configuração do pacote e resources/views/vendor/graphql/graphiql.phpque nos permitirá testar nosso aplicativo usando o GraphiQL.

Crie um modelo de tarefa

Vamos criar um modelo de tarefa e seu arquivo de migração correspondente. Para fazer isso, execute o comando abaixo:

    $ php artisan make:model Task -m

Feito isso, abra o arquivo de migração que foi gerado e atualize o up método conforme abaixo:

    // database/migrations/TIMESTAMP_create_tasks_table.php

    public function up()
    {
      Schema::create('tasks', function (Blueprint $table) {
        $table->increments('id');
        $table->string('title');
        $table->boolean('is_completed')->default(0);
        $table->timestamps();
      });
    }

Adicionamos colunas básicas à taskstabela. Nós definimos a is_completedcoluna como falsepadrão.

Em seguida, precisamos executar as migrações. Mas antes de podermos fazer isso, precisamos configurar nosso banco de dados. Para o propósito deste tutorial, usaremos o SQLite. Então, crie um database.sqlitearquivo dentro do databasediretório. Por último, vamos atualizar o .envarquivo como abaixo:

    // .env

    DB_CONNECTION=sqlite
    DB_DATABASE=FULL_PATH_TO_DATABASE_SQLITE

Agora vamos rodar a migração:

    $ php artisan migrate

Semeadora de banco de dados

Para ter alguns dados para trabalhar, vamos criar uma semeadora de banco de dados para preencher a tabela de tarefas com alguns dados. Execute o comando abaixo:

    $ php artisan make:seeder TasksTableSeeder

Em seguida, dentro do database/factoriesdiretório, crie um novo TaskFactory.phparquivo e cole o código abaixo nele:

    // database/factories/TaskFactory.php

    <?php

    use Faker\Generator as Faker;

    $factory->define(App\Task::class, function (Faker $faker) {
        return [
            'title' => $faker->sentence,
        ];
    });

Apenas especificamos o valor da title coluna, uma vez que já definimos a is_completedcoluna como falsepadrão.

Em seguida, atualize o runmétodo database/seeds/TasksTableSeeder.phpcomo abaixo:

    // database/seeds/TasksTableSeeder.php

    public function run()
    {
      factory(App\Task::class, 5)->create();
    }

Agora, podemos executar o semeador de banco de dados:

    $ php artisan db:seed --class=TasksTableSeeder

Definindo Esquemas

Com a configuração fora do caminho, vamos começar a definir os esquemas para nossa lista de tarefas. Os esquemas descrevem como os dados são formados e quais dados no servidor podem ser consultados. Esquemas podem ser de dois tipos: Consulta e Mutação. Nossos esquemas podem ser definidos internamente config/graphql.php. Nós vamos atualizar este arquivo em breve.

Criando consulta GraphQL

Nossa lista de tarefas terá apenas uma consulta, que será buscar todas as tarefas que foram adicionadas ao servidor GraphQL. Antes de podermos criar uma consulta, precisamos primeiro definir um tipo. Então, vamos definir um Tasktipo. Para fazer isso, crie um novo GraphQLdiretório dentro do appdiretório. Dentro do GraphQLdiretório, crie um novo Typediretório. Dentro do app/GraphQL/Typediretório, crie um novo TaskType.phparquivo e cole o seguinte código:

    // app/GraphQL/Type/TaskType.php

    <?php

    namespace App\GraphQL\Type;

    use GraphQL\Type\Definition\Type;
    use Folklore\GraphQL\Support\Type as GraphQLType;

    class TaskType extends GraphQLType
    {
      protected $attributes = [
        'name' => 'Task',
        'description' => 'A task'
      ];

      public function fields()
      {
        return [
          'id' => [
            'type' => Type::nonNull(Type::int()),
            'description' => 'The id of a task'
          ],
          'title' => [
            'type' => Type::string(),
            'description' => 'The title of a task'
          ],
          'is_completed' => [
            'type' => Type::boolean(),
            'description' => 'The status of a task'
          ],
        ];
      }
    }

Nós damos ao tipo um nome e uma descrição. Além disso, definimos os campos ( idtitleis_completed) que o Tasktipo terá.

Agora vamos criar a consulta. Crie um novo Querydiretório dentro app/GraphQLe dentro do Querydiretório, crie um novo TasksQuery.phparquivo e cole o seguinte código nele:

    // app/GraphQL/Query/TasksQuery.php

    <?php

    namespace App\GraphQL\Query;

    use GraphQL;
    use GraphQL\Type\Definition\Type;
    use Folklore\GraphQL\Support\Query;
    use App\Task;

    class TasksQuery extends Query
    {
      protected $attributes = [
        'name' => 'tasks'
      ];

      public function type()
      {
        return Type::listOf(GraphQL::type('Task'));
      }

      public function resolve($root, $args)
      {
        return Task::all();
      }
    }

Nós damos um nome à consulta e tasks, em seguida, definimos o tipo de consulta (que é o Tasktipo que definimos acima). Como queremos que a consulta busque todas as tarefas que foram criadas, usamos o listOftipo no Tasktipo, que retornará uma matriz de tarefas. Por fim, definimos um resolvemétodo que manipulará a busca real das tarefas. Estamos simplesmente retornando todas as tarefas do banco de dados.

Com nosso tipo e consulta definidos, vamos adicioná-los a config/graphql.php:

    // config/graphql.php

    'schemas' => [
      'default' => [
        'query' => [
          'tasks' => \App\GraphQL\Query\TasksQuery::class,
        ],
        // ...
      ]
    ],

    'types' => [
      'Task' => \App\GraphQL\Type\TaskType::class,
    ],

Criando mutações no GraphQL

Mutações são usadas para executar operações de gravação. Vamos criar duas mutações, que serão usadas para adicionar uma nova tarefa e atualizar o status de uma tarefa, respectivamente. Crie um novo Mutationdiretório dentro app/GraphQLe dentro Mutation, crie um novo NewTaskMutation.phparquivo e cole o seguinte código nele:

    // app/GraphQL/Mutation/NewTaskMutation.php

    <?php

    namespace App\GraphQL\Mutation;

    use GraphQL;
    use GraphQL\Type\Definition\Type;
    use Folklore\GraphQL\Support\Mutation;
    use App\Task;

    class NewTaskMutation extends Mutation
    {
      protected $attributes = [
        'name' => 'newTask'
      ];

      public function type()
      {
        return GraphQL::type('Task');
      }

      public function args()
      {
        return [
          'title' => [
            'name' => 'title',
            'type' => Type::nonNull(Type::string())
          ]
        ];
      }

      public function resolve($root, $args)
      {
        $task = new Task();

        $task->title = $args['title'];
        $task->save();

        return Task::find($task->id);
      }
    }

Nós damos um nome à mutação newTask, então definimos o tipo que esta mutação retornará. Nós definimos um argsmétodo que retorna uma matriz de argumentos que a mutação pode aceitar. A mutação aceitará apenas um argumento, que é o título de uma tarefa. Por fim, definimos um resolvemétodo que faz a inserção real da nova tarefa no banco de dados e retorna a tarefa recém-criada.

E se quisermos validar os dados antes de adicionar uma nova tarefa? Bem, é possível adicionar regras de validação a uma mutação. O pacote laravel-graphql usa o laravel Validatorpara executar a validação contra o args. Existem duas maneiras de adicionar validação a mutações: podemos definir um rulesmétodo e retornar uma matriz contendo as regras para cada argumento, ou definimos as regras diretamente ao definir um argumento. Nós estaremos optando pelo segundo caminho.

Atualize o argsmétodo como abaixo:

    // app/GraphQL/Mutation/NewTaskMutation.php

    public function args()
    {
      return [
        'title' => [
          'name' => 'title',
          'type' => Type::nonNull(Type::string()),
          'rules' => ['required'],
        ]
      ];
    }

Adicionamos uma regra que torna o titleargumento necessário.

Agora, vamos criar a mutação para atualizar o status de uma tarefa. Crie um novo UpdateTaskStatusMutation.phparquivo dentro app/GraphQL/Mutatione cole o seguinte código nele:

    // app/GraphQL/Mutation/UpdateTaskStatusMutation.php

    <?php

    namespace App\GraphQL\Mutation;

    use GraphQL;
    use GraphQL\Type\Definition\Type;
    use Folklore\GraphQL\Support\Mutation;
    use App\Task;

    class UpdateTaskStatusMutation extends Mutation
    {
      protected $attributes = [
        'name' => 'updateTaskStatus'
      ];

      public function type()
      {
        return GraphQL::type('Task');
      }

      public function args()
      {
        return [
          'id' => [
            'name' => 'id',
            'type' => Type::nonNull(Type::int()),
            'rules' => ['required'],
          ],
          'status' => [
            'name' => 'status',
            'type' => Type::nonNull(Type::boolean()),
            'rules' => ['required'],
          ]
        ];
      }

      public function resolve($root, $args)
      {
        $task = Task::find($args['id']);

        if (!$task) {
          return null;
        }

        $task->is_completed = $args['status'];
        $task->save();

        return $task;
      }
    }

Isso é bastante semelhante ao NewTaskMutation. Ele aceita dois argumentos: o ID da tarefa a ser atualizada e o status da tarefa. O resolvemétodo obtém a tarefa com o ID fornecido do banco de dados. Se não houver tarefa com o ID fornecido, simplesmente retornaremos null. Caso contrário, atualizamos a tarefa com o status fornecido e persistimos no banco de dados. Finalmente, retornamos a atualização da tarefa.

Para finalizar as mutações, vamos adicioná-las a config/graphql.php:

    // config/graphql.php

    'schemas' => [
      'default' => [
        // ...
        'mutation' => [
          'newTask' => \App\GraphQL\Mutation\NewTaskMutation::class,
          'updateTaskStatus' => \App\GraphQL\Mutation\UpdateTaskStatusMutation::class,
        ]
      ]
    ],

Testando com o GraphiQL

Até agora, criamos um servidor GraphQL com uma consulta e duas mutações. Vamos agora ver como testamos o servidor usando o GraphiQL. Lembre-se que quando publicamos os arquivos de pacotes laravel-graphql, resources/views/vendor/graphql/graphiql.phptambém foi criado um. Isso nos permitirá testar nosso servidor GraphQL em nosso aplicativo Laravel.

Baixe o aplicativo com o comando abaixo:

    $ php artisan serve

Isso fará com que o aplicativo seja executado e http://127.0.0.1:8000, em seguida, visite http://127.0.0.1:8000/graphiql em seu navegador. O GraphiQL deve agora estar rodando como na imagem abaixo:

Pré-visualização da aplicação

Podemos ver nosso servidor GraphQL em ação:

Captura de tela do teste GraphQL

Conclusão

Neste tutorial, vimos como usar o GraphQL em um aplicativo do Laravel. Nós apenas arranhamos a superfície do trabalho com o GraphQL nos aplicativos do Laravel. No meu próximo tutorial, vamos nos aprofundar mais, pois vamos construir uma API com o GraphQL e o Laravel. Então fique ligado.

O código completo deste tutorial está disponível no GitHub .

Fonte: https://blog.pusher.com/graphql-laravel/