Exemple Livres/Auteurs avec Doctrine¶
Vous pouvez reprendre ici une nouvelle application. On voudrait gérer une bibliothèque avec des Livres et des Auteurs. Les 2 entités se présentent ainsi :

Entités¶
Créons l’entité Auteur
php bin/console make:entity
Répondez aux questions pour ajouter des champs nom et prenom de type string dans
Auteur
.Vérifiez la création du code correspondant dans src/Entity.
Puis faire de même avec l’entité Livre
.
Pour la relation, ajoutez un champ de type relation
à l’entité Livre
.
Faites afficher toutes les possibilités avec le ? :
Class name of the entity to create or update (e.g. AgreeableGnome):
> Livre
created: src/Entity/Livre.php
created: src/Repository/LivreRepository.php
Entity generated! Now let's add some fields!
You can always add more fields later manually or by re-running this command.
New property name (press <return> to stop adding fields):
> titre
Field type (enter ? to see all types) [string]:
>
Field length [255]:
>
Can this field be null in the database (nullable) (yes/no) [no]:
>
updated: src/Entity/Livre.php
Add another property? Enter the property name (or press <return> to stop adding fields):
> annee
Field type (enter ? to see all types) [string]:
> ?
Main types
* string
* text
* boolean
* integer (or smallint, bigint)
* float
Relationships / Associations
* relation (a wizard 🧙 will help you build the relation)
* ManyToOne
* OneToMany
* ManyToMany
* OneToOne
Array/Object Types
* array (or simple_array)
* json
* object
* binary
* blob
Date/Time Types
* datetime (or datetime_immutable)
* datetimetz (or datetimetz_immutable)
* date (or date_immutable)
* time (or time_immutable)
* dateinterval
Other Types
* json_array
* decimal
* guid
Field type (enter ? to see all types) [string]:
> integer
Can this field be null in the database (nullable) (yes/no) [no]:
>
updated: src/Entity/Livre.php
Add another property? Enter the property name (or press <return> to stop adding fields):
> auteur
Field type (enter ? to see all types) [string]:
> relation
What class should this entity be related to?:
> Auteur
What type of relationship is this?
------------ -------------------------------------------------------------------
Type Description
------------ -------------------------------------------------------------------
ManyToOne Each Livre relates to (has) one Auteur.
Each Auteur can relate to (can have) many Livre objects
OneToMany Each Livre can relate to (can have) many Auteur objects.
Each Auteur relates to (has) one Livre
ManyToMany Each Livre can relate to (can have) many Auteur objects.
Each Auteur can also relate to (can also have) many Livre objects
OneToOne Each Livre relates to (has) exactly one Auteur.
Each Auteur also relates to (has) exactly one Livre.
------------ -------------------------------------------------------------------
Relation type? [ManyToOne, OneToMany, ManyToMany, OneToOne]:
> ManyToOne
Is the Livre.auteur property allowed to be null (nullable)? (yes/no) [yes]:
> no
Do you want to add a new property to Auteur so that you can access/update Livre objects from it - e.g. $auteur->getLivres()? (yes/no) [yes]:
> yes
A new property will also be added to the Auteur class so that you can access the related Livre objects from it.
New field name inside Auteur [livres]:
>
Do you want to activate orphanRemoval on your relationship?
A Livre is "orphaned" when it is removed from its related Auteur.
e.g. $auteur->removeLivre($livre)
NOTE: If a Livre may *change* from one Auteur to another, answer "no".
Do you want to automatically delete orphaned App\Entity\Livre objects (orphanRemoval)? (yes/no) [no]:
> no
Voici l’entité Livre
obtenue :
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="App\Repository\LivreRepository")
*/
class Livre
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $titre;
/**
* @ORM\Column(type="integer")
*/
private $annee;
/**
* @ORM\ManyToOne(targetEntity="App\Entity\Auteur", inversedBy="livres")
* @ORM\JoinColumn(nullable=false)
*/
private $auteur;
public function getId(): ?int
{
return $this->id;
}
public function getTitre(): ?string
{
return $this->titre;
}
public function setTitre(string $titre): self
{
$this->titre = $titre;
return $this;
}
public function getAnnee(): ?int
{
return $this->annee;
}
public function setAnnee(int $annee): self
{
$this->annee = $annee;
return $this;
}
public function getAuteur(): ?Auteur
{
return $this->auteur;
}
public function setAuteur(?Auteur $auteur): self
{
$this->auteur = $auteur;
return $this;
}
}
Interaction avec la BD¶
On lance le makemigrations suivi du migrate :
php bin/console make:migration
php bin/console doctrine:migrations:migrate
En cas de problème, on peut forcer la synchonisation du nouveau schéma de BD :
./bin/console doctrine:schema:update --force
Voir la doc correspondante
(Si easy_admin est installé, ajoutons un ou 2 auteurs puis livres dans easy_admin )
Relançons le make:crud¶
php bin/console make:crud
pour les entités Auteur et Livre puis améliorons un peu les templates proposés.
Template de base avec Bootstrap¶
On peut déjà améliorer le template de base base.html.twig avec Bootstrap, ici Bootswatch <https://bootswatch.com/> :
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{% block title %}Bonjour{% endblock %}</title>
{% block stylesheets %}
<link rel="stylesheet" href="https://bootswatch.com/4/yeti/bootstrap.min.css">
{% endblock %}
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
<a class="navbar-brand" href="#">App de Gestion Livres/Auteurs</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarColor01" aria-controls="navbarColor01" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarColor01">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Livres</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Auteurs</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">A propos</a>
</li>
</ul>
</div>
</nav>
<div class="container">
{% block body %}
{% endblock %}
</div>
{% block javascripts %}
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"
integrity="sha256-pasqAKBDmFT4eHoN2ndd6lN370kFiGUFyTiUHWhU7k8="
crossorigin="anonymous">
</script>
<script src="https://bootswatch.com/_vendor/popper.js/dist/umd/popper.min.js">
</script>
<script src="https://bootswatch.com/_vendor/bootstrap/dist/js/bootstrap.min.js">
</script>
{% endblock %}
</body>
</html>
on utilise les dépôts en ligne pour simplifier ici. Les liens sont à compléter …
Puis ensuite on fait hériter les autres templates de base.html.twig et on peut par exemple utiliser les boutons Bootstrap pour améliorer le rendu de la page index.html.twig des livres :
<button type="button" class="btn btn-info btn-sm">
<a href="{{ path('livre_show', {'id': livre.id}) }}">show</a>
</button>
<button type="button" class="btn btn-info btn-sm">
<a href="{{ path('livre_edit', {'id': livre.id}) }}">edit</a>
</button>
Si besoin, ajoutez une méthode __toString() à l’entité Auteur :
<?php
public function __toString()
{
return $this->getPrenom() . ' ' . $this->getNom();
}
Faites de même dans l’entité Livre
Testez !