Aller au contenu principal

Modifications de données

Mise à jour et suppression de données avec Doctrine dans Symfony 7

Notions théoriques

Dans Symfony 7, pour mettre à jour ou supprimer une entité, il est recommandé d'utiliser l'injection de dépendance avec le Repository.

Voici les principales étapes :

  1. Injecter le Repository dans votre contrôleur.
  2. Utiliser le Repository pour trouver l'entité.
  3. Effectuer les modifications ou la suppression.
  4. Utiliser les méthodes du Repository pour persister les changements.

Une mise à jour

Voici comment réaliser une mise à jour de données dans la base de données :

use App\Entity\Player;
use App\Repository\PlayerRepository;

class GameController extends AbstractController
{
public function __construct(private PlayerRepository $playerRepository)
{
}

public function updatePlayer(int $id): Response
{
$player = $this->playerRepository->find($id);

if (!$player) {
throw $this->createNotFoundException('No player found for id '.$id);
}

$player->setName('New Name');
$this->playerRepository->save($player, true);

return new Response('Player updated!');
}
}

Une suppression

Voici comment réaliser une suppression de données dans la base de données :

public function deletePlayer(int $id): Response
{
$player = $this->playerRepository->find($id);

if (!$player) {
throw $this->createNotFoundException('No player found for id '.$id);
}

$this->playerRepository->remove($player, true);

return new Response('Player deleted!');
}

Exemple pratique

Ajoutons deux actions à notre GameController pour mettre à jour et supprimer un joueur dans Symfony 7 :

use App\Entity\Player;
use App\Repository\PlayerRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class GameController extends AbstractController
{
public function __construct(private PlayerRepository $playerRepository)
{
}

#[Route('/game/update_player/{id}', name: 'update_player')]
public function updatePlayer(int $id): Response
{
$player = $this->playerRepository->find($id);

if (!$player) {
throw $this->createNotFoundException('No player found for id '.$id);
}

$player->setName('Updated Player');
$this->playerRepository->save($player, true);

return new Response('Player updated!');
}

#[Route('/game/delete_player/{id}', name: 'delete_player')]
public function deletePlayer(int $id): Response
{
$player = $this->playerRepository->find($id);

if (!$player) {
throw $this->createNotFoundException('No player found for id '.$id);
}

$this->playerRepository->remove($player, true);

return new Response('Player deleted!');
}
}
La promotion de propriété de constructeur

Pourquoi private PlayerRepository $playerRepository dans les paramètres du constructeur ?

Voici une explication du constructeur de l'exemple pratique et une alternative plus explicite (plus classique).

Explication du constructeur de l'exemple

class GameController extends AbstractController
{
public function __construct(private PlayerRepository $playerRepository)
{
}

// ... reste du code ...

}

Dans ce constructeur :

  1. Le mot-clé private avant le paramètre $playerRepository est une fonctionnalité de PHP 8 appelée "promotion de propriété de constructeur" (constructor property promotion).

  2. Cette syntaxe combine la déclaration du paramètre du constructeur et la déclaration de la propriété de classe en une seule ligne.

  3. Elle crée automatiquement une propriété privée $playerRepository dans la classe et lui assigne la valeur passée au constructeur.

  4. Le corps de la méthode est vide car toute la logique nécessaire (création de la propriété et assignation) est gérée par la promotion de propriété.

Cette syntaxe est concise mais peut être moins évidente pour les développeurs non familiers avec les dernières fonctionnalités de PHP.

Alternative plus explicite

Voici une version plus explicite et potentiellement plus facile à comprendre pour certains développeurs :

class GameController extends AbstractController
{
private PlayerRepository $playerRepository;

public function __construct(PlayerRepository $playerRepository)
{
$this->playerRepository = $playerRepository;
}

// ... reste du code ...
}

Dans cette version :

  1. La propriété $playerRepository est explicitement déclarée dans la classe.

  2. Le constructeur reçoit le PlayerRepository comme paramètre.

  3. Dans le corps du constructeur, nous assignons explicitement le paramètre à la propriété de la classe.

Cette approche est plus verbeuse mais peut être plus claire pour les développeurs habitués à un style plus traditionnel de PHP ou pour ceux qui apprennent le langage.

Les deux approches sont fonctionnellement équivalentes. Le choix entre elles dépend souvent des préférences de l'équipe de développement et des conventions du projet.

remarque

La version avec promotion de propriété est plus concise et devient de plus en plus courante dans les projets PHP modernes, tandis que la version explicite peut être préférée pour sa clarté dans certains contextes, notamment pédagogiques.

Test de mémorisation/compréhension


Dans Symfony 7, comment injecte-t-on le Repository dans un contrôleur ?


Quelle méthode utilise-t-on pour supprimer une entité avec le Repository dans Symfony 7 ?


Comment gère-t-on les erreurs si une entité n'est pas trouvée dans Symfony 7 ?


Quelle méthode du Repository doit-on appeler pour enregistrer les modifications dans Symfony 7 ?


Comment définit-on une route dans Symfony 7 ?


Quelle fonctionnalité de PHP 8 est utilisée dans le constructeur de l'exemple pratique ?


Dans l'exemple avec promotion de propriété, quel mot-clé est utilisé avant le paramètre du constructeur ?


Quelle est la principale différence entre les deux approches présentées pour le constructeur ?


Pourquoi le corps de la méthode du constructeur est-il vide dans l'exemple avec promotion de propriété ?


Quelle version de PHP a introduit la fonctionnalité de promotion de propriété de constructeur ?


Quelle est la principale raison pour laquelle certains développeurs pourraient préférer l'approche plus explicite ?


Quelle approche devient de plus en plus courante dans les projets PHP modernes ?


Quel est l'avantage principal de l'approche avec promotion de propriété ?


TP pour réfléchir et résoudre des problèmes

Votre défi pour aujourd'hui consiste à créer 2 nouvelles actions dans votre GameController pour permettre de mettre à jour et de supprimer un joueur.

  • La 1ère méthode updatePlayerTwo doit mettre à jour le nom du joueur avec l'ID 2.
  • La 2ème méthode deletePlayerThree doit supprimer le joueur avec l'ID 3.
Une solution