ORM

Note

si vous voulez générer automatiquement les modèles, consultez la partie génération des modèles .

Une classe de type modèle est juste un bon vieil objet php sans héritage.
Les modèles sont situés par défaut dans le dossier appmodels.
Le mappage relationnel d’objets (ORM) repose sur les annotations ou les attributs des membres (depuis PHP8) dans la classe du modèle.

Définition de modèles

Un modèle basique

  • Un modèle doit définir sa clé primaire en utilisant l’annotation @id sur les membres concernés.

  • Les membres sérialisés doivent avoir des getters et setters.

  • Sans autre annotation, une classe correspond à une table du même nom dans la base de données, chaque membre correspond à un champ de cette table.

app/models/User.php
 1namespace models;
 2
 3use Ubiquity\attributes\items\Id;
 4
 5class User{
 6
 7   #[Id]
 8   private $id;
 9
10   private $firstname;
11
12   public function getFirstname(){
13      return $this->firstname;
14   }
15   public function setFirstname($firstname){
16      $this->firstname=$firstname;
17   }
18}

Mappage

Table->Classe

Si le nom de la table est différent du nom de la classe, l’annotation @table permet de préciser le nom de la table.

app/models/User.php
 1namespace models;
 2
 3use Ubiquity\attributes\items\Table;
 4use Ubiquity\attributes\items\Id;
 5
 6#[Table('user')]
 7class User{
 8
 9   #[Id]
10   private $id;
11
12   private $firstname;
13
14   public function getFirstname(){
15      return $this->firstname;
16   }
17   public function setFirstname($firstname){
18      $this->firstname=$firstname;
19   }
20}

Champ->Membre

Si le nom d’un champ est différent du nom du membre de la classe associé, l’annotation @column permet de spécifier un nom de champ différent.

app/models/User.php
 1namespace models;
 2
 3use Ubiquity\attributes\items\Table;
 4use Ubiquity\attributes\items\Id;
 5use Ubiquity\attributes\items\Column;
 6
 7#[Table('user')
 8class User{
 9
10   #[Id]
11   private $id;
12
13   #[Column('column_name')]
14   private $firstname;
15
16   public function getFirstname(){
17      return $this->firstname;
18   }
19   public function setFirstname($firstname){
20      $this->firstname=$firstname;
21   }
22}

Associations

Note

Convention de nommage
Les noms des champs des clés étrangères sont constitués du nom de la clé primaire de la table référencée suivi du nom de la table référencée dont la première lettre est en majuscule.
Exemple : idUser pour la table user dont la clé primaire est id.

ManyToOne

Un utilisateur appartient à une organisation :

../_images/manyToOne.png
app/models/User.php
 1 namespace models;
 2
 3use Ubiquity\attributes\items\ManyToOne;
 4use Ubiquity\attributes\items\Id;
 5use Ubiquity\attributes\items\JoinColumn;
 6
 7 class User{
 8
 9   #[Id]
10   private $id;
11
12   private $firstname;
13
14   #[ManyToOne]
15   #[JoinColumn(className: \models\Organization::class, name: 'idOrganization', nullable: false)]
16   private $organization;
17
18   public function getOrganization(){
19      return $this->organization;
20   }
21
22   public function setOrganization($organization){
23      $this->organization=$organization;
24   }
25}

L’annotation @joinColumn ou l’attribut JoinColumn le spécifie :

  • Le membre $organisation est une instance de modelsOrganization.

  • La table user possède une clé étrangère idOrganization faisant référence à la clé primaire de l’organisation.

  • Cette clé étrangère n’est pas nulle => un utilisateur aura toujours une organisation.

OneToMany

Une organisation a de nombreux utilisateurs :

../_images/oneToMany.png
app/models/Organization.php
 1namespace models;
 2
 3use Ubiquity\attributes\items\OneToMany;
 4use Ubiquity\attributes\items\Id;
 5
 6class Organization{
 7
 8   #[Id]
 9   private $id;
10
11   private $name;
12
13   #[OneToMany(mappedBy: 'organization', className: \models\User::class)]
14   private $users;
15}

Dans ce cas, l’association est bidirectionnelle.
L’annotation @oneToMany doit juste préciser :

  • La classe de chaque utilisateur dans le tableau users : modelsUser.

  • la valeur de @mappedBy est le nom de l’attribut association-mapping du côté propriétaire : $organisation dans la classe User.

ManyToMany

  • Un utilisateur peut appartenir à des groupes.

  • Un groupe se compose de plusieurs utilisateurs.

../_images/manyToMany.png
app/models/User.php
 1namespace models;
 2
 3use Ubiquity\attributes\items\ManyToMany;
 4use Ubiquity\attributes\items\Id;
 5use Ubiquity\attributes\items\JoinTable;
 6
 7class User{
 8
 9   #[Id]
10   private $id;
11
12   private $firstname;
13
14   #[ManyToMany(targetEntity: \models\Group::class, inversedBy: 'users')]
15   #[JoinTable(name: 'groupusers')]
16   private $groups;
17
18}
app/models/Group.php
 1namespace models;
 2
 3use Ubiquity\attributes\items\ManyToMany;
 4use Ubiquity\attributes\items\Id;
 5use Ubiquity\attributes\items\JoinTable;
 6
 7class Group{
 8
 9   #[Id]
10   private $id;
11
12   private $name;
13
14   #[ManyToMany(targetEntity: \models\User::class, inversedBy: 'groups')]
15   #[JoinTable(name: 'groupusers')]
16   private $users;
17
18}

Si les conventions de nommage ne sont pas respectées pour les clés étrangères,
il est possible de spécifier les champs associés.

app/models/Group.php
 1namespace models;
 2
 3use Ubiquity\attributes\items\ManyToMany;
 4use Ubiquity\attributes\items\Id;
 5use Ubiquity\attributes\items\JoinTable;
 6
 7class Group{
 8
 9   #[Id]
10   private $id;
11
12   private $name;
13
14   #[ManyToMany(targetEntity: \models\User::class, inversedBy: 'groupes')]
15   #[JoinTable(name: 'groupeusers',
16   joinColumns: ['name'=>'id_groupe','referencedColumnName'=>'id'],
17   inverseJoinColumns: ['name'=>'id_user','referencedColumnName'=>'id'])]
18   private $users;
19
20}

Annotations ORM

Annotations pour les classes

@annotation

rôle

propriétés

rôle

@database

Définit l’offset de la base de données associée (défini dans le fichier de configuration)

@table

Définit le nom de la table associée.

Annotations pour les membres

@annotation

rôle

propriétés

rôle

@id

Définit la ou les clés primaires.

@column

Spécifie les caractéristiques du champ associé.

name

Nom du champ associé

nullable

true si la valeur peut être nulle

dbType

Type du champ dans la base de données

@transient

Indique que le champ n’est pas persistant.

Associations

@annotation (extends)

rôle

properties [optional]

rôle

@manyToOne

Définit une association à valeur unique avec une autre classe d’entité.

@joinColumn (@column)

Indique la clé étrangère dans l’association manyToOne.

className

Classe du membre

[referencedColumnName]

Nom de la colonne associée

@oneToMany

Définit une association à valeurs multiples avec une autre classe d’entité.

className

Classe des objets du membre

[mappedBy]

Nom de l’attribut de mappage d’association du côté propriétaire.

@manyToMany

Définit une association à valeurs multiples avec une multiplicité de plusieurs à plusieurs.

targetEntity

Classe des objets du membre

[inversedBy]

Nom du membre associé du côté inverse

[mappedBy]

Nom du membre associé du côté propriétaire

@joinTable

Définit la table d’association pour l’association many-to-many.

name

Le nom de la table d’association

[joinColumns]

@column => name et referencedColumnName pour ce côté

[inverseJoinColumns]

@column => name et referencedColumnName pour l’autre côté