Relations entre les entités
Comment gérer les relations entre les entités avec Doctrine

Notions théoriques
Dans une base de données relationnelle, les tables peuvent être liées entre elles par des relations.
Doctrine supporte les types de relations suivants :
- OneToOne,
- OneToMany,
- ManyToOne
- et ManyToMany.
Exemple de relation 'Catégories d'un joueur'

Par exemple, si chaque joueur de notre jeu a plusieurs personnages,
nous pourrions avoir une relation OneToMany entre l'entité Player et une nouvelle entité Character.
Pour cela, nous devons :
- ajouter une propriété
charactersàPlayer - ajouter une propriété
playeràCharacter, - utiliser les attributs de Doctrine pour définir la relation.
Exemple de mise en application
Voici une entité Character dans le fichier src/Entity/Character.php :
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use App\Repository\CharacterRepository;
#[ORM\Entity(repositoryClass: CharacterRepository::class)]
#[ORM\Table(name: 'tbl_character')]
class Character
{
#[ORM\Id, ORM\GeneratedValue, ORM\Column(type: "integer")]
private ?int $id = null;
#[ORM\Column(type: "string", length: 100)]
private string $name;
#[ORM\ManyToOne(targetEntity: Player::class, inversedBy: "characters")]
private Player $player;
public function getId(): ?int
{
return $this->id;
}
public function getName(): string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getPlayer(): Player
{
return $this->player;
}
public function setPlayer(Player $player): self
{
$this->player = $player;
return $this;
}
}
Exemple de relation 'Personnages d'un joueur'

Et voici l'ajout de la propriété characters dans l'entité Player :
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use App\Repository\PlayerRepository;
#[ORM\Entity(repositoryClass: PlayerRepository::class)]
#[ORM\Table(name: 'tbl_player')]
class Player
{
// ... autres propriétés ...
#[ORM\OneToMany(targetEntity: Character::class, mappedBy: "player")]
private Collection $characters;
public function __construct()
{
$this->characters = new ArrayCollection();
}
public function getCharacters(): Collection
{
return $this->characters;
}
public function addCharacter(Character $character): self
{
if (!$this->characters->contains($character)) {
$this->characters[] = $character;
$character->setPlayer($this);
}
return $this;
}
public function removeCharacter(Character $character): self
{
if ($this->characters->removeElement($character)) {
if ($character->getPlayer() === $this) {
$character->setPlayer(null);
}
}
return $this;
}
}
Test de mémorisation/compréhension
TP pour réfléchir et résoudre des problèmes
Votre défi pour aujourd'hui consiste à créer une relation entre les joueurs et les personnages
Étape 1 : Créez l'entité Character avec une propriété player en relation ManyToOne vers Player, et ajoutez la relation OneToMany correspondante dans Player.
Étape 2 : Codez l'action createCharacter dans le GameController pour créer un personnage associé à un joueur existant.
Dans une relation bidirectionnelle (OneToMany / ManyToOne), il faut initialiser les deux côtés.
$character->setPlayer($player) définit le côté ManyToOne (côté base de données).
Pour que $player->getCharacters() reste cohérent en mémoire dans la même requête,
il faut aussi appeler $player->addCharacter($character).
Doctrine ne synchronise les deux côtés que lors du prochain chargement depuis la base de données.
Une solution
Vous devez être connecté pour voir le contenu.