Skip to content

Api REST

Pour créer une API REST avec Laravel

Créer un nouveau projet Laravel

laravel new nomProjet

  • Pour le choix du kit de départ, sélectionner None
  • Le framework de test: PHPUnit
  • Base de données : MySQL
  • On nous propose d'exécuter npm install, choisir "oui".

Pour pouvoir générer facilement les routes de notre API on foit installer le module API

php artisan install:api

La processus crée une migration pour la table contenant les jetons d'accès ainsi qu'un fichier routes/api.php dans lequel on pourra définir les routes de l'API.

On crée ensuite le contrôleur de ressource pour l'API

php artisan make:controller NomController --api

Et dans le fichier /routes/api.php on fait générer les routes en ajoutant

Route::apiResource('/nomController', NomController::class);

Routes personnalisées

apiResource va créer toutes les routes nécessaires aux actions CRUD. Si vous créez des méthodes différentes dans votre contrôleur, vous devrez enregistrer les routes manuellement. Elles seront déclarées selon le modèle suivant

Route::get('/chemin', [NomController::class, 'NomMéthodeDuController']);
Rappel, puisque cette route est dans le fichier routes/api.php, le chemin aura /api comme préfixe.

Il est important d'enregistrer ces routes AVANT d'enregistrer la ressource api. Le premier exemple ci-dessous fonctionne

<?php
Route::post('/chats/adopter', [ChatController::class, 'adopterChat']);
Route::apiResource('/chats', ChatController::class)->middleware(['auth:sanctum', 'verified']);

Alors que le suivant ne fonctionne pas

<?php
// La route personnalisée ne sera pas créée adéquatement car la ressource API "vole" toutes les routes débutant par /api/chats
Route::apiResource('/chats', ChatController::class)->middleware(['auth:sanctum', 'verified']);
Route::post('/chats/adopter', [ChatController::class, 'adopterChat']);

Utiliser les ressource JSON

Pour créer la ressource

php artisan make:resource NomResource

Ensuite on peut personnaliser la ressource.

  • Par défaut, la ressource renvoie l'objet converti en array
<?php
public function toArray(Request $request): array {
  return parent::toArray($request);
}
  • En personnalisant la ressource, on peut utiliser les relations, créer des nouvelles propriétés, modifier le nom des propriétés existantes, etc.
<?php

class UserResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @return array<string, mixed>
     */
    public function toArray(Request $request): array
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'email' => $this->email,
            'chats' => ChatResource::collection($this->chats),
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at,
        ];
    }
}
  • Dans le contrôleur, on retourne la ressource JSON (voir exemple)

Exemple

<?php

Schema::create('chats', function (Blueprint $table) {
    $table->id();
    $table->string('nom',150);
    $table->foreignId('user_id');
    $table->timestamps();
    $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
<?php

public function index()
{
    return ChatResource::collection(Chat::all()->sortBy('nom'));
}
<?php

public function proprio(){
    return $this->belongsTo(User::class, 'user_id');
}
<?php
namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

class ChatResource extends JsonResource
{
    /**
    * Transform the resource into an array.
    *
    * @return array<string, mixed>
    */
    public function toArray(Request $request): array
    {
        return [
            'id' => $this->id,
            'nom' => $this->nom,
            'proprio' => $this->proprio->name, // utilisation de la relation
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at,
        ];
    }
<?php
namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

class UserResource extends JsonResource
{
    /**
    * Transform the resource into an array.
    *
    * @return array<string, mixed>
    */
    public function toArray(Request $request): array
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'email' => $this->email,
            'chats' => ChatResource::collection($this->chats),
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at,
        ];
    }
}

Particularité des ressources JSON en Laravel

Par défaut, Laravel ajoute une couche de protection contre le détournement de JSON (JSON Highjacking), ce qui fait que toutes les données retournées par Laravel sont enveloppées dans un objet data.

{
    "data": [
        {
            "id":3,
            "nom":"Bettye Hartmann",
            "proprio":"Graham Muller","created_at":"2025-09-24T12:50:29.000000Z","updated_at":"2025-09-24T12:50:29.000000Z"
        },
        {
            "id":10,
            "nom":"Lora Farrell",
            "proprio":"Jefferey Schultz","created_at":"2025-09-24T12:50:29.000000Z","updated_at":"2025-09-24T12:50:29.000000Z"
        }
        ,
        {
            "id":6,
            "nom":"Ms. Margarett Kilback DVM",
            "proprio":"Dr. Maribel Ruecker","created_at":"2025-09-24T12:50:29.000000Z","updated_at":"2025-09-24T12:50:29.000000Z"
        }
    ]
}

Il faudra donc s'assurer que les requêtes HTTP faites traitent ce format de données. On peut créer une interface générique pour traiter les données.

export interface ApiResponse<Type> {
  data?: Type,
  error? : {
    code : number,
    message : string
  }
}

On utilise ce type dans nos appels avec HttpClient dans les services

getChats(): Observable<ApiResponse<Chat[]>>{
    return this.httpClient.get<ApiResponse<Chat[]>>(url);
  }

Puis dans les composants on peut récupérer l'information

import {ChatService} from '../../../services/chat-service';
import {Chat} from '../../../models/chat';
import {Subscription} from 'rxjs';

export class ListeChatsComponent {
  private chatService: ChatService = inject(ChatService);

    chats: Chat[] = [];
    chatAbonnement$!: Subscription;

    ngOnInit(): void {
        this.getChats();
    }

    getChats(): void {
        this.chatAbonnement$ = this.chatService.getChats().subscribe({
        next: (res) => {
            res.data ? this.chats = res.data : this.chats = [];
            console.log(this.chats);
        },
        error: (error) => {
            console.error(error);
        }
        })
    }


}