Nouveau : Datasets open source gratuits disponibles !Decouvrir →
🐘
Intermediaire 30 min Laravel

Laravel avec GraphQL

Pourquoi Laravel avec GraphQL ?

L'adoption de GraphQL dans une application Laravel peut offrir des avantages significatifs, notamment en termes de performance et d'efficacité de développement. En effet, plutôt que de récupérer un ensemble fixe de données lors d'une requête HTTP, GraphQL permet aux clients de spécifier exactement ce qu'ils veulent recevoir, réduisant ainsi le temps de réponse et améliorant la qualité des données renvoyées.

Un cas d'usage concret est une application mobile qui affiche des informations sur un produit. Au lieu de récupérer toutes les propriétés d'un produit lors d'une requête HTTP standard, l'application mobile peut spécifier que elle veut uniquement le nom, le prix et la description du produit. Avec GraphQL, cela peut être fait en une seule requête, permettant à l'application de récupérer précisément ce qu'elle a besoin.

Prerequis

  • Connaissance de base de Laravel (version 8 ou supérieure recommandée)
  • Connaissance des bases de données SQL
  • Connaissance du langage PHP
  • Installation de Composer et Node.js
  • Un serveur local comme XAMPP, WAMP ou MAMP

Concepts fondamentaux

1. Schema GraphQL

Le schema de GraphQL est une description détaillée de toutes les requêtes et mutations disponibles pour l'API. Il définit le format des données qui peuvent être récupérées et comment elles sont structurées.

Exemple de schéma en PHP :

use GraphQL\Type\Schema;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\ObjectType;

$schema = new Schema([
    'query' => new ObjectType([
        'name' => 'Query',
        'fields' => [
            'user' => [
                'type' => Type::string(),
                'args' => [
                    'id' => ['type' => Type::nonNull(Type::int())],
                ],
                'resolve' => function ($root, $args) {
                    // Récupération des données de l'utilisateur
                    return "Utilisateur avec ID {$args['id']}";
                },
            ],
        ],
    ]),
]);

2. Resolver

Un resolver est une fonction qui définit comment récupérer les données pour une requête ou une mutation. Il prend comme arguments le root objet, les arguments de la requête et les contexte.

Exemple de resolver en PHP :

$resolveFunction = function ($root, $args) {
    // Logique pour récupérer les données
    return "Données récupérées";
};

3. Mutations

Les mutations sont des requêtes qui modifient l'état du serveur. Elles permettent d'effectuer des opérations comme la création, la mise à jour ou la suppression de données.

Exemple de mutation en PHP :

$mutationType = new ObjectType([
    'name' => 'Mutation',
    'fields' => [
        'createUser' => [
            'type' => Type::string(),
            'args' => [
                'name' => ['type' => Type::nonNull(Type::string())],
                'email' => ['type' => Type::nonNull(Type::string())],
            ],
            'resolve' => function ($root, $args) {
                // Logique pour créer un utilisateur
                return "Utilisateur créé";
            },
        ],
    ],
]);

Mise en pratique : projet fil rouge

Nous allons construire une application simple de gestionnaire de tâches. L'application permettra aux utilisateurs de récupérer, ajouter et mettre à jour des tâches.

Étape 1 : Création du projet Laravel

composer create-project --prefer-dist laravel/laravel task-manager
cd task-manager

Étape 2 : Installation d'GraphQL dans Laravel

composer require webonyx/graphql-php

Étape 3 : Configuration de la base de données

Modifier le fichier .env pour configurer votre base de données.

Exemple de configuration :

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=task_manager
DB_USERNAME=root
DB_PASSWORD=

Créer la table tasks dans la base de données.

Migration :

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;

class CreateTasksTable extends Migration
{
    public function up()
    {
        Schema::create('tasks', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->text('description')->nullable();
            $table->boolean('completed')->default(false);
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('tasks');
    }
}

Exécuter la migration :

php artisan migrate

Étape 4 : Création des modèles et contrôleurs

Créer un modèle Task.

php artisan make:model Task

Modèle Task.php :

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Task extends Model
{
    protected $fillable = ['title', 'description', 'completed'];
}

Créer un contrôleur pour les tâches.

php artisan make:controller TaskController --api

Contrôleur TaskController.php :

namespace App\Http\Controllers;

use App\Models\Task;
use Illuminate\Http\Request;
use GraphQL\Type\Schema;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\QueryType;

class TaskController extends Controller
{
    public function index()
    {
        return response()->json(Task::all());
    }

    public function show($id)
    {
        $task = Task::find($id);
        if (!$task) {
            return response()->json(['error' => 'Task not found'], 404);
        }
        return response()->json($task);
    }

    public function store(Request $request)
    {
        $task = Task::create($request->all());
        return response()->json($task, 201);
    }

    public function update(Request $request, $id)
    {
        $task = Task::find($id);
        if (!$task) {
            return response()->json(['error' => 'Task not found'], 404);
        }
        $task->update($request->all());
        return response()->json($task);
    }

    public function destroy($id)
    {
        $task = Task::find($id);
        if (!$task) {
            return response()->json(['error' => 'Task not found'], 404);
        }
        $task->delete();
        return response()->json(null, 204);
    }
}

Étape 5 : Configuration de la route GraphQL

Créer un fichier graphql.php dans le répertoire config.

Fichier config/graphql.php :

return [
    'schema' => 'Query',
];

Modifier le fichier routes/api.php pour ajouter une route GraphQL.

Route routes/api.php :

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\TaskController;

Route::get('/graphql', function () {
    return \GraphQL\HTTP\query(
        (new \GraphQL\Schema\Schema(['query' => new QueryType])),
        null,
        null,
        null,
        request()->all()
    );
});

Étape 6 : Création du schéma GraphQL

Créer un fichier schema.php dans le répertoire app/GraphQL.

Fichier app/GraphQL/schema.php :

use GraphQL\Type\Schema;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\ObjectType;

$schema = new Schema([
    'query' => new ObjectType([
        'name' => 'Query',
        'fields' => [
            'tasks' => [
                'type' => Type::listOf(Type::string()),
                'resolve' => function () {
                    return Task::all()->map->only(['id', 'title', 'description'])->toArray();
                },
            ],
            'task' => [
                'type' => Type::string(),
                'args' => [
                    'id' => ['type' => Type::nonNull(Type::int())],
                ],
                'resolve' => function ($root, $args) {
                    return Task::find($args['id'])->only(['id', 'title', 'description']);
                },
            ],
        ],
    ]),
]);

return $schema;

Étape 7 : Ajout des resolvers

Ajouter des resolvers pour les mutations.

Fichier app/GraphQL/mutations.php :

use GraphQL\Type\Schema;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\MutationType;

$mutationType = new MutationType([
    'name' => 'Mutation',
    'fields' => [
        'createTask' => [
            'type' => Type::string(),
            'args' => [
                'title' => ['type' => Type::nonNull(Type::string())],
                'description' => ['type' => Type::string()],
            ],
            'resolve' => function ($root, $args) {
                Task::create($args);
                return "Task created";
            },
        ],
        'updateTask' => [
            'type' => Type::string(),
            'args' => [
                'id' => ['type' => Type::nonNull(Type::int())],
                'title' => ['type' => Type::string()],
                'description' => ['type' => Type::string()],
            ],
            'resolve' => function ($root, $args) {
                Task::find($args['id'])->update($args);
                return "Task updated";
            },
        ],
        'deleteTask' => [
            'type' => Type::string(),
            'args' => [
                'id' => ['type' => Type::nonNull(Type::int())],
            ],
            'resolve' => function ($root, $args) {
                Task::find($args['id'])->delete();
                return "Task deleted";
            },
        ],
    ],
]);

$schema = new Schema([
    'query' => new ObjectType([
        'name' => 'Query',
        'fields' => [
            'tasks' => [
                'type' => Type::listOf(Type::string()),
                'resolve' => function () {
                    return Task::all()->map->only(['id', 'title', 'description'])->toArray();
                },
            ],
            'task' => [
                'type' => Type::string(),
                'args' => [
                    'id' => ['type' => Type::nonNull(Type::int())],
                ],
                'resolve' => function ($root, $args) {
                    return Task::find($args['id'])->only(['id', 'title', 'description']);
                },
            ],
        ],
    ]),
    'mutation' => $mutationType,
]);

return $schema;

Étape 8 : Test de l'API GraphQL

Lancer le serveur local et accéder à http://localhost:8000/graphql pour tester les requêtes.

Requête pour obtenir toutes les tâches :

query {
    tasks {
        id
        title
        description
    }
}

Requête pour créer une nouvelle tâche :

mutation {
    createTask(title: "Nouvelle Tâche", description: "Description de la nouvelle tâche") {
        result
    }
}

Erreurs frequentes et debugging

1. Call to undefined function GraphQL\GraphQL::schema()

Le problème peut être causé par une version incompatble de graphql-php.

Code incorrect :

use GraphQL\GraphQL;

Correction :

use GraphQL\Type\Schema;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\ObjectType;

2. Call to undefined method App\Models\Task::only()

Le problème peut être causé par une mauvaise utilisation de la méthode only.

Code incorrect :

return Task::find($args['id'])->only(['id', 'title', 'description']);

Correction :

return Task::find($args['id'])->getAttributes();

3. Non-scalar return type hinting is not allowed for a public method in class App\Http\Controllers\TaskController

Le problème peut être causé par une mauvaise définition des types de retour dans les méthodes du contrôleur.

Code incorrect :

public function index()
{
    return Task::all();
}

Correction :

public function index()
{
    return response()->json(Task::all());
}

Pour aller plus loin

  1. Intégration avec Apollo Client pour le frontend

  2. Utilisation de GraphQL Shield pour la gestion des autorisations

  3. Optimisation des performances avec DataLoader

Défi pratique

Créer une application complète de gestion de projets utilisant GraphQL. L'application devrait permettre de créer, lire, mettre à jour et supprimer des projets et leurs tâches associées.

Besoin d'aide sur Laravel ?

Besoin d'aide sur un projet technique ? Decrivez-le pour des conseils personnalises.

Recevoir des conseils

Questions frequentes

Qu'est-ce que GraphQL et pourquoi utiliser-il avec Laravel?
GraphQL est une alternative au protocole REST qui permet aux clients de demander exactement les données dont ils ont besoin, en les regroupant dans des requêtes multiples. Avec Laravel, vous pouvez intégrer facilement GraphQL pour offrir une API plus efficace et performante.
Comment installer GraphQL dans un projet Laravel existant?
Pour installer GraphQL dans Laravel, vous pouvez utiliser le package Lighthouse qui est officiellement soutenu par la communauté. Exécutez les commandes `composer require nuwave/lighthouse` pour l'installer et ensuite exécutez `php artisan lighthouse:install` pour configurer l'application.
Quelle est la différence entre un resolver et une directive en GraphQL?
En GraphQL, un resolver est une fonction qui définit comment récupérer les données pour une requête particulière. En revanche, une directive permet de modifier le comportement d'une query ou mutation, comme par exemple ajouter des filtres spécifiques ou calculer des valeurs dynamiquement.

Pages liees

Chaque semaine, le meilleur de la tech francaise

Tendances, salaires, outils et opportunites — directement dans votre boite mail.

Gratuit. Desabonnement en un clic. Pas de spam.