Symfony VS Laravel : comparaison des Frameworks PHP pour des APIs performantes

Laravel et Symfony sont deux frameworks PHP très populaires pour le développement d'applications web. Lorsque l'on envisage une utilisation en mode API, ces frameworks offrent des approches variées dans la gestion des endpoints, controllers, services, répositories et ORM (Object-Relational Mapping). Mais quels sont les différences fondamentales entre Laravel et Symfony sur ces aspects spécifiques ? C'est ce que nous allons découvrir dans cet article !
symfonyvslaravel.png
NathanA.jpg
Nathan ARMANETlogo Linkedin
Développeur fullstack, j'adore relever des défis techniques ! Mis à jour le 12 Nov 2024

17+

ans
d'experience

60+

experts
techniques

100K

écoutes de notre podcast
logo Axopen

Avant toute chose, si vous souhaitez un comparatif complet de Laravel et Symfony, n'hésitez pas à consuler notre page "VERSUS" !

Définition des Endpoints

Définir des Endpoints en Laravel : simplicité et flexibilité des routes

Laravel simplifie la définition des endpoints avec son système de routes. Ces routes peuvent être configurées de manière explicite dans des fichiers situés dans le dossier routes/, notamment api.php pour les API. Le système de routes est très flexible et permet de définir des endpoints RESTful en une seule ligne de code :

// routes/api.php

Route::get('/users', [UserController::class, 'index']);
Route::post('/users', [UserController::class, 'store']);
Route::put('/users/{id}', [UserController::class, 'update']);
Route::delete('/users/{id}', [UserController::class, 'destroy']);

Laravel propose également des groupes de routes et des middlewares pour simplifier la gestion des authentifications et autorisations.


Route::middleware('jwt:READ_USER')->get('/users', [UserController::class, 'index']);

Gestion des Endpoints avec Symfony : routes et API Platform

En Symfony, les routes peuvent être définies directement dans le fichier de configuration (config/routes.yaml), annotées dans les contrôleurs, ou déclarées dans des fichiers spécifiques de type annotations. En mode APIUne API est un programme permettant à deux applications distinctes de communiquer entre elles et d’échanger des données., l'approche la plus courante consiste à utiliser les annotations dans les contrôleurs, notamment avec l'aide du bundle API Platform pour gérer les routes RESTREST (REpresentational State Transfer) est un style d'architecture logicielle qui fonctionne sous un certain nombre de contraintes. plus efficacement :


use Symfony\Component\Routing\Annotation\Route;

class UserController
{
    #[Route('/users', name: 'app_users_index')]
    public function index()
    {
        // Code pour lister les utilisateurs
    }
}

Dans ce cas, la gestion des authentifications et autorisations se réalise aussi par annotaion.

Controllers

Contrôleurs dans Laravel : rapidité avec Artisan et structure REST

Les contrôleurs dans Laravel sont généralement simples à mettre en place grâce à la commande php artisan make:controller. En mode API, ils sont souvent centrés sur des méthodes pour chaque action REST (index, store, update, destroy, etc.). Les contrôleurs Laravel favorisent l'utilisation de services, répositories et validation intégrés via l'injection de dépendances.


namespace App\Http\Controllers;

use App\Services\UserService;
use Illuminate\Http\Request;

class UserController extends Controller
{
    protected $userService;

    public function __construct(UserService $userService)
    {
        $this->userService = $userService;
    }

    public function index()
    {
        return response()->json($this->userService->getAllUsers());
    }
}

Laravel offre également un middleware api par défaut pour simplifier les contrôleurs en mode API.

Contrôleurs Symfony : architecture orientée services et flexibilité

Les contrôleurs SymfonyFramework PHP permettant de développer des applications web. fonctionnent souvent avec des services injectés via le container de services de Symfony. Ils sont définis en tant que services eux-mêmes et n'ont pas forcément besoin d'étendre une classe parente comme c'est le cas dans Laravel. En mode API, le contrôleur pourrait ressembler à ceci :


namespace App\Controller;

use App\Service\UserService;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Annotation\Route;

class UserController
{
    private $userService;

    public function __construct(UserService $userService)
    {
        $this->userService = $userService;
    }

    #[Route('/users', name: 'app_users_index')]
    public function index(): JsonResponse
    {
        return new JsonResponse($this->userService->getAllUsers());
    }
}

Services

Services en Laravel : séparation de la logique Métier et contrôleurs

Laravel encourage l'usage de services via des classes spécialisées souvent situées dans un répertoire comme App\Services. Ces services sont ensuite injectés dans les contrôleurs, ce qui permet de séparer la logique métier des contrôleurs eux-mêmes.

Exemple de service Laravel :


namespace App\Services;

use App\Models\User;

class UserService
{
    public function getAllUsers()
    {
        return User::all();
    }
}

Les services peuvent être enregistrés dans le service container de Laravel, et injectés automatiquement dans les contrôleurs.

Services dans Symfony : service container et architecture modulaire

Symfony est réputé pour son approche orientée services. Chaque service est enregistré dans le service container et peut être injecté automatiquement dans d'autres services ou contrôleurs. La logique métier est ainsi bien séparée.

Exemple de service Symfony :


namespace App\Service;

use App\Repository\UserRepository;

class UserService
{
    private $userRepository;

    public function __construct(UserRepository $userRepository)
    {
        $this->userRepository = $userRepository;
    }

    public function getAllUsers()
    {
        return $this->userRepository->findAll();
    }
}

Les services sont définis dans config/services.yaml ou via des annotations.

Répositories

Laravel

Laravel utilise l'Eloquent ORM, où chaque modèle correspond à une table dans la base de données. Les répositories

peuvent être créés manuellement si nécessaire, mais généralement, les méthodes Eloquent fournissent déjà la plupart des

fonctionnalités CRUD.

Par exemple, pour interagir avec les utilisateurs dans un modèle User, vous pouvez simplement utiliser :

$users = User::all();

Si vous souhaitez une couche de répositories explicite, vous pouvez définir un répertoire Repositories et structurer l'accès aux données manuellement.

Symfony

Symfony utilise le design pattern Repository par défaut grâce à l'ORM Doctrine. Chaque entité a un répository associé qui est responsable des interactions avec la base de données. Le répository est généré automatiquement ou peut être personnalisé pour des requêtes complexes.

Exemple de répository Symfony :


namespace App\Repository;

use App\Entity\User;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;

class UserRepository extends ServiceEntityRepository
{
    public function __construct(ManagerRegistry $registry)
    {
        parent::__construct($registry, User::class);
    }

    public function findActiveUsers()
    {
        return $this->createQueryBuilder('u')
            ->where('u.isActive = :active')
            ->setParameter('active', true)
            ->getQuery()
            ->getResult();
    }
}

Modèles et Migrations

Les modèles et les migrations permettent de gérer la structure de la base de données de manière programmatique dans Laravel et Symfony. Ils facilitent la synchronisation entre les tables de la base de données et les objets métier de l'application.

Laravel

Dans Laravel, les modèles sont définis dans le dossier app/Models et représentent les tables de la base de données via l'ORM Eloquent. Voici un exemple de modèle User :


namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    use HasFactory;

    protected $fillable = ['name', 'email', 'password'];
}

Dans cet exemple, la propriété $fillable indique les colonnes que l'on peut remplir de manière massive lors de la création ou de la mise à jour d'un utilisateur.

Il faut bien noté que les propriétés (ie colones) ne sont pas exiplicitement definit dans la classe !

Avec Eloquent, vous pouvez ensuite interagir avec la table users en utilisant des méthodes simples :

// Créer un utilisateur

User::create(['name' => 'Alice', 'email' => 'alice@example.com', 'password' => bcrypt('password')]);

// Récupérer tous les utilisateurs
$users = User::all();

// Trouver un utilisateur par ID
$user = User::find(1);

Pour créer la table users, Laravel utilise des migrations, définies via la commande php artisan make:migration create_users_table. Voici un exemple de fichier de migration :


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

class CreateUsersTable extends Migration
{
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->string('password');
            $table->timestamps();
        });
    }

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

Ici, la méthode up crée la table avec des colonnes pour id, name, email, et password. La méthode down supprime la table si la migration est annulée.

Symfony

En Symfony, les entités sont généralement créées dans le dossier src/Entity avec Doctrine. Une entité User pourrait ressembler à ceci :


namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\UserRepository")
 */
class User
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=100)
     */
    private $name;

    /**
     * @ORM\Column(type="string", length=180, unique=true)
     */
    private $email;

    /**
     * @ORM\Column(type="string")
     */
    private $password;

    // Getters et setters...
}

Avec cette entité, Symfony gère les interactions avec la table user en utilisant Doctrine. Pour sauvegarder un utilisateur :

$user = new User();
$user->setName('Alice');
$user->setEmail('alice@example.com');
$user->setPassword(password_hash('password', PASSWORD_BCRYPT));

$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($user);
$entityManager->flush();

Les migrations en Symfony se créent avec php bin/console make:migration, et elles génèrent automatiquement un fichier SQL qui reflète les changements apportés aux entités. Voici un exemple de migration générée :


public function up(Schema $schema): void
{
    $this->addSql('CREATE TABLE user (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(100) NOT NULL, email VARCHAR(180) NOT NULL, password VARCHAR(255) NOT NULL, UNIQUE INDEX UNIQ_8D93D649E7927C74 (email), PRIMARY KEY(id))');
}

public function down(Schema $schema): void
{
    $this->addSql('DROP TABLE user');
}

Ces migrations assurent que la base de données est synchronisée avec les entités en ajoutant, modifiant ou supprimant les tables et colonnes en fonction des changements dans le code.

Ainsi, avec des modèles (Laravel) ou des entités (Symfony) et des migrations, les deux frameworks permettent de maintenir la structure de la base de données de manière cohérente et facilement versionnable.

Notre verdict : Laravel ou Symfony pour vos APIs ?

Laravel et Symfony sont tous deux des frameworks puissants pour le développement d'APIs, mais leur approche diffère grandement :

  • Laravel mise sur une simplicité et une rapidité de développement grâce à Eloquent, des services et des routes faciles à configurer au detriment du typage et de la rigeur de code.
  • Symfony, en revanche, offre une architecture plus stricte et orientée services avec Doctrine, API Platform et des conventions qui favorisent l'évolution du projet et la maintenance tout tant incluant les avancés de php8.

Bien que Laravel puisse sembler plus abordable pour les non initiés, nous vous conseillons de plutot choisir le framework symfony.