Introduction à la doctrine ORM et au motif de mappeur de données en PHP

Introduction à la doctrine ORM et au motif de mappeur de données en PHP

Objectif

Apprenez les concepts de base de la doctrine ORM, implémentant le modèle de mappeur de données avec PHP.

Exigences

  • Composer (gestionnaire de packages PHP)
  • Une configuration de lampe de travail
  • Comprendre la programmation de base orientée objet et PHP
  • Comprendre les concepts de base de données de base

Conventions

  • # - nécessite que les commandes Linux soient exécutées avec des privilèges racine
    directement en tant qu'utilisateur racine ou en utilisant Sudo commande
  • $ - Exige que les commandes Linux soient exécutées en tant qu'utilisateur non privilégié régulier

Introduction

Le modèle de mappeur de données est un schéma architectural au moyen de laquelle il est possible d'atteindre la séparation entre une couche de persistance de données (dans ce cas une base de données MySQL) et une représentation de données en mémoire (dans ce cas, des objets PHP), afin que les deux couches puissent être séparées et ignorant complètement les uns des autres, respectant ainsi la séparation des préoccupations.

Dans ce tutoriel, nous verrons comment faire nos premiers pas avec la doctrine, une implémentation de modèle de mappeur de données qui fait partie de la Syfony PHP Framework, mais peut également être utilisé seul.

La création de la base de données

Avant quoi que ce soit d'autre, nous devons créer la base de données que nous utiliserons pour la persistance des données. Dans ce tutoriel, nous représenterons un utilisateur et ses articles dans un blog:

MARIADB [(Aucun)]> Créer un blog de base de données; MariaDB [(Aucun)]> Graite tous les privilèges sur le blog.* À 'TesUser' @ 'localhost' identifié par 'TestPassword'; MariaDb [(aucun)]> Privilèges de rinçage; MariaDb [(aucun)]> sortie; 


Installer et initialiser la doctrine

La prochaine étape de notre voyage sera l'installation de la doctrine: nous utiliserons compositeur, Le package PHP et le gestionnaire de dépendances. Dans la racine de notre projet, nous créons le compositeur.Fichier JSON, spécifiant doctrine / orm comme dépendance:

"require": "doctrine / orm": "^ 2.6 " 
Copie

Maintenant, pour procéder à l'installation, tandis que dans le même répertoire, ouvrez un terminal et exécutez:

$ Installation du compositeur

Le compositeur installera la doctrine et toutes ses dépendances à l'intérieur du fournisseur répertoire qu'il créera. Une fois la doctrine installée, nous devons l'initialiser. Enregistrez le code ci-dessous dans un fichier (pour ce tutoriel, nous l'appellerons bootstrap.php):

 'Blog'; 'utilisateur' => 'TesUser', 'Motword' => 'TestPassword', 'Host' => 'LocalHost', 'Driver' => 'PDO_MYSQL']; // Obtenez l'entité Manager $ entity_manager = doctrine \ orm \ entitymanager :: create ($ connection_parameters, $ configuration); 
Copie

Tout d'abord, nous avons besoin à la ligne 2 Le fichier de compositeur Autoload automatique.php, qui s'occupe de la mise en œuvre des bibliothèques nécessaires.

En appelant le createannotationMetadataconfiguration méthode statique du Installation classe à la ligne 5, nous avons commencé à configurer la doctrine. Cette méthode prend 5 arguments, mais nous ne fournirons que les deux premiers, laissant le reste à leurs valeurs par défaut, car nous ne nous intéressons pas pour le moment.



Le premier argument à la ligne 6 est un tableau de chemins où se trouvent les cours d'entités dans notre projet. Une entité est une classe qui représente une ligne dans la base de données (la rappésenation en mémoire que nous avons mentionnée ci-dessus): Dans notre exemple, nous utiliserons deux entités: auteur et post.

Le deuxième argument de la ligne 7 prend une valeur booléenne et définit si nous travaillons en mode «dev» ou non. Cela définit le comportement de la doctrine sur les objets proxy et la mise en cache: lorsque en mode «Dev», les objets proxy seront régénérés sur chaque demande et la mise en cache se produira en mémoire, car il est supposé que pendant le développement, les modifications se produiront très souvent souvent. Nous allons le définir sur vrai pour le moment.

Après cela, nous devons spécifier les paramètres de connexion dans les lignes 11-16, sous la forme d'un tableau associatif contenant, dans l'ordre, le nom de la base de données, l'utilisateur de la base de données, le mot de passe de la base de données, l'hôte de la base de données et le pilote à utiliser pour accéder à la base de données. Il est important de remarquer qu'à un niveau inférieur, la doctrine utilise PDO pour interagir avec la base de données, et il est conçu pour être agnostique de base de données.

Enfin, nous avons créé une instance de l'objet EntityManager à la ligne 20, appelant la méthode d'usine «créer» de la classe EntityManager, passant le tableau d'informations de connexion que nous venons de définir comme le premier paramètre, et le Configuration objet comme le second. L'objet EntityManager nous donnera accès à toutes nos entités et nous rendra facilement gérer leur persistance et leur cycle de vie.

Créer nos entités

Il est temps de créer nos entités. Tout comme nous l'avons dit dans la configuration, nous allons créer un répertoire «entités» à la racine de notre projet pour stocker nos entités. La première entité que nous allons définir est Auteur:

Copie

Nous avons défini notre première entité très simple. Nous avons utilisé annotations pour donner à la doctrine les informations nécessaires pour les gérer. D'abord dans la ligne 5, en utilisant, @Entité Nous disons à la doctrine que la classe doit être considérée comme une entité, qui sera persistée dans le auteur table de base de données. Dans ce cas, nous avons utilisé l'annotation @table (name = ”auteur”) à la ligne 6 pour le spécifier, mais dans cette situation, il est redondant, et nous aurions pu l'omettre complètement: il est facultatif, et s'il n'est pas utilisé, l'entité sera persisté dans une table nommée d'après le sans réserve nom du cours.

Chaque propriété de la classe correspond à une colonne du tableau, et nous devons fournir des informations sur le type de données de table. Le $ id la propriété, par exemple, représente la clé principale du tableau: nous le déclarons en utilisant le @Identifiant Annotation à la ligne 11.

La valeur du identifiant la colonne sera générée automatiquement, c'est pourquoi nous avons utilisé le @GeneratedValue Annotation à la ligne 12. Il n'a sens que lorsqu'il est associé à @identifiant, Et en l'utilisant, il est même possible de spécifier la stratégie de génération à adopter (si aucune n'est spécifiée, elle sera par défaut AUTO).

Le type de données utilisé pour notre clé principale sera Petit, que nous avons défini via le @Column (type = "smallInt") Annotation à la ligne 13. Les deux autres propriétés sont $ First_name et $ last_name, et elles sont définies avec la même technique. Ils sont de type chaîne: Lors de l'utilisation de MySQL, il sera traduit par Varchar Type de données de base de données. Pour une référence complète sur les associations de types de données, vous pouvez consulter cette page.

Lorsque vous utilisez la doctrine, la visibilité des propriétés d'une classe d'entité peut être soit protégé ou privé mais pas public.



Nous n'avons pas encore défini les getters et les setteurs pour la classe. Il n'est pas nécessaire de le faire manuellement, car la doctrine peut le faire pour nous, et nous verrons comment dans un instant, nous avons encore une autre entité pour définir, Poste:

Copie

Nous avons introduit deux nouveaux types de données. Le premier est texte Dans la ligne 23 qui mappera et convertira les données de chaîne sans une longueur maximale: lors de l'utilisation de MySQL, il sera converti en Texte long Type de données. Le second est DateTime Dans la ligne 28, pour notre $ date propriété. Il sera traduit dans le même type pour MySQL, et dans un cas de PHP DateTime objet.

Maintenant, nous pouvons générer nos getters et nos setteurs, mais avant de le faire, nous devons créer le cliquette.php Script à la racine de notre projet: il est nécessaire pour utiliser la doctrine de la ligne de commande:

Copie

Maintenant, ouvrez un shell terminal dans le répertoire racine du projet et exécutez la commande Linux suivante:

$ php fournisseur / bac / doctrine orm: générer des entités .

La commande ci-dessus générera des getters et des setteurs pour les entités trouvées, et les placera dans le répertoire spécifié. Maintenant, si nous jetons un coup d'œil au Auteur Entité, nous pouvons voir que Getters et Setters ont été générés:

identifiant;  / ** * Définir FirstName. * * @param String $ firstName * * @return auteur * / fonction publique setFirstName ($ firstName) $ this-> first_name = $ firstName; retourner $ ceci;  / ** * Obtenez FirstName. * * @return String * / public function getFirstName () return $ this-> first_name;  / ** * Set LastName. * * @param string $ lastname * * @return auteur * / fonction publique setLastName ($ lastName) $ this-> last_name = $ lastname; retourner $ ceci;  / ** * Get LastName. * * @return String * / Fonction publique getLastName () return $ this-> last_name;  
Copie

La même chose s'est produite pour le Poste entité:

identifiant;  / ** * Définir le titre. * * @param string $ title * * @return Post * / public function SettLitle ($ title) $ this-> title = $ title; retourner $ ceci;  / ** * Obtenez le titre. * * @return String * / public function getTitle () return $ this-> title;  /** * Définir le texte. * * @param String $ text * * @return Post * / public function setText ($ text) $ this-> text = $ text; retourner $ ceci;  / ** * Obtenez du texte. * * @return String * / public function getText () return $ this-> text;  /** * Régler la date. * * @param \ dateTime $ Date * * @return Post * / public function setDate ($ date) $ this-> date = $ date; retourner $ ceci;  /** * Avoir un rendez-vous. * * @return \ dateTime * / public function getDate () return $ this-> date;  
Copie

Définir la relation entre les entités

Pour notre exemple, nous voulons définir un bidirectionnel à plusieurs relation entre nos entités, où bidirectionnel signifie que chaque entité détient une référence à l'autre. La relation entre un auteur et ses messages est de plusieurs à un (un auteur peut rédiger de nombreux messages et de nombreux messages peuvent appartenir à un auteur). Utiliser la doctrine, définir une telle association est très simple:

Copie

Nous avons ajouté une nouvelle propriété dans chaque entité. En auteur, c'est $ messages dans la ligne 16, et dans l'entité post, $ auteur Dans la ligne 36. Quel type de type de données ces variables contiendront-elles? Le premier, $ messages sera un exemple de doctrine Arraycolletion Objet: c'est une classe spéciale utilisée pour mieux gérer la collection d'entités.

Le deuxième, $ auteur, dans Poste.php, sera une instance de l'entité de l'auteur, représentant l'auteur de la publication: comme indiqué précédemment, chaque entité détient une référence à l'autre.

De façon similaire à ce que nous avons fait pour les autres propriétés, nous avons défini la relation en utilisant des annotations. Dans notre cas, puisque nous avons affaire à une relation bidirectionnelle un à plusieurs, nous avons utilisé le @Onetomany annotation à la ligne 13, dans l'entité de l'auteur, et @Manytoone dans la ligne 32 en post.

Dans les deux cas, avec Cible Nous avons défini quelle entité la propriété pointe vers. Par exemple dans le cas de l'auteur $ messages propriété, l'entité cible est publique. Comme vous pouvez le voir, nous avons utilisé respectivement le inversé par et cartographié par annotations. Ces annotations sont utilisées pour indiquer à la doctrine quelle propriété, de l'autre côté de la relation, fait référence à l'objet: inversé par doit être utilisé dans le côté qui possède le CLÉ ÉTRANGÈRE, (Dans ce cas, l'entité post).

Comme vous pouvez le voir, dans l'auteur, nous avons utilisé cartographié par, spécifiant que dans le entité cibler Post, la propriété correspondante est $ auteur. Nous avons également introduit un nouveau paramètre, Cascade, le régler sur «tout». Cela signifie qu'en persistant ou en supprimant l'entité de la base de données, tous ses messages seront également influencés: par exemple, la suppression d'un utilisateur entraînera également la suppression de tous ses messages. Est ce que nous définissons via Sur Supprimer Cascade en code SQL.

Vice versa, dans l'entité post, qui contient la clé étrangère dans la base de données, nous avons utilisé inversé par, Dire la doctrine que dans l'auteur de l'entité cible, la propriété qui fait référence à l'objet est des postes. Nous avons également utilisé le @Joincumn Annotation à la ligne 33, spécifiant les colonnes impliquées dans la jointure SQL, définissant la clé étrangère pas nullable (Pas nul).

Une fois la relation entre les deux entités définie, nous devons mettre à jour les méthodes nécessaires pour gérer les propriétés ajoutées. Encore une fois, nous courons:

$ php fournisseur / bac / doctrine orm: générer des entités .


Générer le schéma de base de données

Dans notre exemple, nous avons suffisamment de données pour pouvoir générer notre schéma de base de données. Encore une fois, la doctrine peut nous aider, en la générant automatiquement en fonction de nos annotations. Tout ce que nous devons faire est d'exécuter la commande Linux suivante:

$ php fournisseur / bac / doctrine Orm: schéma-tool: mise à jour - Force

Si tout se passe bien, les tables de base de données seront générées, vérifions-la:

MariaDb [(Aucun)]> Décrivez le blog.auteur; + ------------ + -------------- + ------ + ----- + -------- - + ---------------- + | Champ | Type | NULL | Clé | Par défaut | Extra | + ------------ + -------------- + ------ + ----- + -------- - + ---------------- + | ID | smallInt (6) | Non | Pri | NULL | auto_increment | | First_name | varchar (255) | Non | | NULL | | | Last_name | varchar (255) | Non | | NULL | | + ------------ + -------------- + ------ + ----- + -------- - + ---------------- + Mariadb [(Aucun)]> Décrivez le blog.poste; + ----------- + -------------- + ------ + ----- + --------- + ---------------- + | Champ | Type | NULL | Clé | Par défaut | Extra | + ----------- + -------------- + ------ + ----- + --------- + ---------------- + | ID | smallInt (6) | Non | Pri | NULL | auto_increment | | auteur_id | smallInt (6) | Non | Mul | NULL | | | Titre | varchar (255) | Non | | NULL | | | Texte | LongText | Non | | NULL | | | Date | DateTime | Non | | NULL | | +-----------+--------------+------+-----+---------+----------------+ 
Copie

Comme prévu, les tableaux correspondant à notre entité ont été générés et reflète les annotations que nous avons spécifiées. Le code SQL utilisé pour les générer respectivement:

MariaDb [(Aucun)]> Show Create Table Blog Table.auteur; Table: Auteur Create Table: Create Table 'Author' ('id' smallInt (6) pas null auto_increment, 'first_name' varchar (255) Collater utf8_unicode_ci pas null, 'last_name' varchar (255) collate utf8_unicode_ci non null, clé primaire (clé primaire (clé primaire (255) 'id')) moteur = innodb auto_increment = 2 charset par défaut = utf8 collate = utf8_unicode_ci mariaDb [(non)]> afficher le blog de table de création de table.poste; Table: Post Create Table: Create Table 'Post' ('id' smallInt (6) pas null Auto_inCment, 'Author_id' smallInt (6) Not Null, 'Title' Varchar (255) Collate UTF8_UNICODE_CI Not Null, 'Text' Collate LongText Collate utf8_unicode_ci not null, 'date' datetime not null, key primaire ('id'), key 'idx_5a8a6c8df675f31b' ('auteur_id'), contrainte 'fk_5a8a6c8df675f31b' forest key ('audac_id') références 'auteur' ('id')) Moteur = innodb auto_increment = 2 charse par défaut = utf8 collate = utf8_unicode_ci 
Copie

Utilisation du gestionnaire d'entité

Maintenant, il est temps de montrer comment utiliser le entité:

setFirstName ("John") -> setlastName ("Smith"); $ entity_manager-> persistant ($ auteur); // Créer un nouveau post $ post = (Nouvelles entités \ poster ()) -> SettItle ("Hello wold") -> setText ("Ceci est un post de test") -> setAuthor ($ auteur) -> setDate (nouveau DateTime ()); // Ajouter le message de la liste des messages de l'auteur. Puisque nous avons utilisé Cascade = "all", nous // n'avons pas besoin de persister le message séparément: il sera persisté lorsque vous persistant // l'auteur $ auteur-> addPost ($ post); // enfin rincer et exécuter la transaction de base de données $ entity_manager-> flush (); 
Copie

En exécutant ce code, nous avons créé un auteur et son premier message, puis nous avons ajouté le message à la collection de publication de l'auteur et enfin nous les avons persisté à la base de données. Avec le persister() Méthode Nous disons à la doctrine de gérer l'entité, tandis que la transaction de la base de données réelle ne se produit que lorsque vous appelez affleurer(). Si nous jetons maintenant un œil au auteur et poste Tableau, nous pouvons voir qu'un nouveau record existe dans les deux:

MariaDb [(Aucun)]> Sélectionner * dans le blog.auteur; + ---- + ------------ + ----------- + | ID | First_name | Last_name | + ---- + ------------ + ----------- + | 1 | John | Smith | + ---- + ------------ + ----------- + MariaDB [(Aucun)]> Sélectionnez * dans le blog.poste; + ---- + ----------- + ------------ + ------------------- - + --------------------- + | ID | auteur_id | Titre | Texte | Date | + ---- + ----------- + ------------ + ------------------- - + --------------------- + | 1 | 1 | Bonjour Wold | Ceci est un post de test | 2018-04-17 08:37:44 | +----+-----------+------------+---------------------+---------------------+ 
Copie

Nous pouvons également utiliser le gestionnaire d'entités pour récupérer une entité existante, par exemple:

// Récupérer l'auteur par son nom de famille $ auteur = $ entity_manager-> getRepository ('entités \ auteur') -> findOneby (['last_name' => 'smith']); 
Copie

Conclusions

Le but de ce tutoriel était de vous présenter le modèle de mappeur de données en PHP en utilisant la doctrine: nous avons vu comment configurer et obtenir un gestionnaire d'entité, comment définir deux entités de base et définir une relation commune entre eux via des annotations.

La doctrine est une bibliothèque très puissante: vous pouvez utiliser la documentation du projet pour commencer à la maîtriser, j'espère que cela pourrait être un point de départ minimal.

Tutoriels Linux connexes:

  • Choses à installer sur Ubuntu 20.04
  • Ampache Raspberry Pi Installation
  • Comment créer une pile de lampe basée sur Docker à l'aide de Docker sur…
  • Comment installer la pile de lampe sur Almalinux
  • Choses à faire après l'installation d'Ubuntu 20.04 Focal Fossa Linux
  • Une introduction à l'automatisation Linux, des outils et des techniques
  • Ubuntu 20.04 astuces et choses que vous ne savez peut-être pas
  • Mint 20: Mieux que Ubuntu et Microsoft Windows?
  • Manipulation de Big Data pour le plaisir et le profit Partie 1
  • Ubuntu 20.04 WordPress avec installation Apache