Table des matières
http://docs.doctrine-project.org/projects/doctrine-orm/en/2.1/reference/xml-mapping.html
Le pilote de mapping XML vous permet de fournir les métadonnées ORM sous forme de documents XML.
Le pilote XML est soutenue par un document de schéma XML qui décrit la structure d'un document de mapping. La version la plus récente du document de schéma XML est disponible en ligne à http://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd . Afin de pointer vers la dernière version du document d'une branche particulière version stable, ajoutez le numéro de version, à savoir: doctrine de cartographie-2.0.xsd . Le moyen le plus commode de travailler avec des fichiers de mappage XML est d'utiliser un éditeur IDE qui peut fournir la finalisation du code basé sur un tel document de Scemaa XML. Ce qui suit est un aperçu d'un document de mapping XML avec le bon xmlns/XSI installé pour le dernier code.
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> ... </doctrine-mapping>
Le document de mapping XML d'une classe est chargée à la demande la première fois qu'il est demandé et ensuite stocké dans le cache de métadonnées. Afin de travailler, ce qui exige certaines conventions:
<?php $driver->setFileExtension('.xml');
Il est recommandé de mettre tous les documents de mapping XML dans un seul dossier, mais vous pouvez répartir les documents sur plusieurs dossiers si vous voulez. L'ordre d'appel du XmlDriver où chercher pour vos documents de mapping sera fournit par un tableau de chemins du premier argument du constructeur, comme ceci:
<?php $config = new \Doctrine\ORM\Configuration(); $driver = new \Doctrine\ORM\Mapping\Driver\XmlDriver(array('/path/to/files1', '/path/to/files2')); $config->setMetadataDriverImpl($driver);
Le projet Symfony a parrainé un pilote qui simplifie l'utilisation du pilote XML. Les changements entre le pilote d'origine sont:
La configuration de ce client fonctionne un peu différent:
<?php $namespaces = array( 'MyProject\Entities' => '/path/to/files1', 'OtherProject\Entities' => '/path/to/files2' ); $driver = new \Doctrine\ORM\Mapping\Driver\SimplifiedXmlDriver($namespaces); $driver->setGlobalBasename('global'); // global.orm.xml
Pour un démarrage rapide, voici un exemple de petits documents qui fait usage de plusieurs éléments communs:
// Doctrine.Tests.ORM.Mapping.User.dcm.xml <?xml version="1.0" encoding="UTF-8"?> <doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> <entity name="Doctrine\Tests\ORM\Mapping\User" table="cms_users"> <indexes> <index name="name_idx" columns="name"/> <index columns="user_email"/> </indexes> <unique-constraints> <unique-constraint columns="name,user_email" name="search_idx" /> </unique-constraints> <lifecycle-callbacks> <lifecycle-callback type="prePersist" method="doStuffOnPrePersist"/> <lifecycle-callback type="prePersist" method="doOtherStuffOnPrePersistToo"/> <lifecycle-callback type="postPersist" method="doStuffOnPostPersist"/> </lifecycle-callbacks> <id name="id" type="integer" column="id"> <generator strategy="AUTO"/> <sequence-generator sequence-name="tablename_seq" allocation-size="100" initial-value="1" /> </id> <field name="name" column="name" type="string" length="50" nullable="true" unique="true" /> <field name="email" column="user_email" type="string" column-definition="CHAR(32) NOT NULL" /> <one-to-one field="address" target-entity="Address" inversed-by="user"> <cascade><cascade-remove /></cascade> <join-column name="address_id" referenced-column-name="id" on-delete="CASCADE" on-update="CASCADE"/> </one-to-one> <one-to-many field="phonenumbers" target-entity="Phonenumber" mapped-by="user"> <cascade> <cascade-persist/> </cascade> <order-by> <order-by-field name="number" direction="ASC" /> </order-by> </one-to-many> <many-to-many field="groups" target-entity="Group"> <cascade> <cascade-all/> </cascade> <join-table name="cms_users_groups"> <join-columns> <join-column name="user_id" referenced-column-name="id" nullable="false" unique="false" /> </join-columns> <inverse-join-columns> <join-column name="group_id" referenced-column-name="id" column-definition="INT NULL" /> </inverse-join-columns> </join-table> </many-to-many> </entity> </doctrine-mapping>
Soyez conscient que la classe des noms spécifiés dans les fichiers XML doit être pleinement qualifié.
La référence XML Element explique toutes les balises et les attributs que la cartographie Doctrine schéma XSD définit. Vous devriez lire le Basic-, Association- et chapitres l'héritage de Mapping pour comprendre ce que chacune de ces définitions signifie dans le détail.
Chaque fichier de mappage XML contient la définition d'une entité, qui précisent que l'élément <entity /> est un enfant direct de l'élément <doctrine-mapping />:
<doctrine-mapping>
<entity name="MyProject\User" table="cms_users" repository-class="MyProject\UserRepository">
<!-- definition here -->
</entity>
</doctrine-mapping>
Les attributs obligatoires:
Les attributs optionnels:
Chaque classe d'entité peut contenir de zéro à l'infini des champs qui sont gérés par Doctrine. Vous pouvez les définir en utilisant l'élément <field /> comme un enfant à l'élément <entity />. L'élément champ n'est utilisé que pour les types primitifs qui ne sont pas l'ID de l'entité. Pour la cartographie ID, vous devez utiliser l'élément <id />.
<entity name="MyProject\User"> <field name="name" type="string" length="50" /> <field name="username" type="string" unique="true" /> <field name="age" type="integer" nullable="true" /> <field name="isActive" column="is_active" type="boolean" /> <field name="weight" type="decimal" scale="5" precision="2" /> </entity>
Les attributs obligatoires:
Nom - Le nom de la propriété/champ donnée de l'entité de la classe PHP;
Attributs optionnels:
Une entité doit avoir au moins un <id /> élément. Pour les clés composites, vous pouvez spécifier plusieurs ID-élément, les touches cependant porteuse sont recommandés pour une utilisation avec Doctrine2. Le champ ID permet de définir les propriétés de l'identifiant et permet à un sous-ensemble des attributs de l'élément <field />:
<entity name="MyProject\User"> <id name="id" type="integer" column="user_id" /> </entity>
Les attributs obligatoires:
Attributs optionnels:
En utilisant la définition ci-dessus simplifiée, Doctrine ne s'appuiera sur aucune stratégie identifiant de cette entité. Cela signifie que vous devez définir manuellement l'identifiant avant d'appeler EntityManager#persist($entity). C'est la stratégie que l'on appelle ASSIGNED.
Si vous voulez passer à la stratégie de génération d'identifiants vous avez à un <generator /> à l'intérieur du id-élément. Bien sûr, cela ne fonctionne que pour les clés de substitution. Pour les clés composites, vous avez toujours à utiliser la stratégie ASSIGNED.
<entity name="MyProject\User"> <id name="id" type="integer" column="user_id"> <generator strategy="AUTO" /> </id> </entity>
Les valeurs suivantes sont autorisées pour l'attribut de la stratégie <generator />
Si vous utilisez la stratégie de séquence, vous pouvez définir un élément supplémentaire pour décrire la séquence:
<entity name="MyProject\User"> <id name="id" type="integer" column="user_id"> <generator strategy="SEQUENCE" /> <sequence-generator sequence-name="user_seq" allocation-size="5" initial-value="1" /> </id> </entity>
Attributs requis pour <sequence-generator />:
Les attributs facultatifs pour les <sequence-generator />:
| NOTE : Si vous souhaitez implémenter une application multi-fournisseur compatible, vous devez spécifier et, en outre définir les éléments <sequence-generator /> , si la doctrine choisit la stratégie de séquence pour une plate-forme. | |
Parfois, vous voulez définir une classe qui hérite de plusieurs entités, ce qui en soi n'est pas une entité cependant. Le chapitre sur le Mapping de l'héritage décrit une superclasse cartographiée en détail. Vous pouvez la définir en utilisant la balise XML <mapped-superclass />.
<doctrine-mapping>
<mapped-superclass name="MyProject\BaseClass">
<field name="created" type="datetime" />
<field name="updated" type="datetime" />
</mapped-superclass>
</doctrine-mapping>
Les attributs obligatoires:
Vous pouvez imbriquer un nombre illimité de <field /> et <many-to-one/> unidirectionnel ou <one-to-one/> associations à l'intérieur d'une superclasse mappée.
Il existe actuellement deux stratégies de persistance d'héritage que vous pouvez choisir lors de la définition des entités qui héritent les uns des autres. L'héritage de table simple sauve les domaines de la hiérarchie d'héritage complète dans un seul tableau, l'héritage table jointe crée une table pour chaque entité combinant les champs en utilisant des conditions de jointure.
Vous pouvez spécifier le type d'héritage dans le <entity élément /> puis utilisez la <discriminator-column /> et <discriminator-mapping attributs />.
<entity name="MyProject\Animal" inheritance-type="JOINED"> <discriminator-column name="discr" type="string" /> <discriminator-map> <discriminator-mapping value="cat" class="MyProject\Cat" /> <discriminator-mapping value="dog" class="MyProject\Dog" /> <discriminator-mapping value="mouse" class="MyProject\Mouse" /> </discriminator-map> </entity>
Les valeurs autorisées pour l'héritage de type d'attribut sont JOINED ou SINGLE_TABLE.
Toutes les définitions relatives héritage doivent être définies sur l'entité racine de la hiérarchie.
Vous pouvez définir les méthodes callback lifecycle sur votre entités en utilisant l'élement <lifecycle-callbacks/>
<entity name="Doctrine\Tests\ORM\Mapping\User" table="cms_users"> <lifecycle-callbacks> <lifecycle-callback type="prePersist" method="onPrePersist" /> </lifecycle-callbacks> </entity>
Vous pouvez définir les relations One-To-One en utilisant l'élément <one-to-one/>. Les attributs obligatoires et facultatifs dépendent des associations qui sont sur l'autre côté.
Le côté inverse de la cartographie est aussi simple que:
<entity class="MyProject\User"> <one-to-one field="address" target-entity="Address" mapped-by="user" /> </entity>
Attributs requis pour à l'inverse du One-To-One:
Le côté inverse de cette cartographie ressemble à ceci:
<entity class="MyProject\Address"> <one-to-one field="user" target-entity="User" inversed-by="address" /> </entity>
Attributs requis pour noter One-to-One:
Les attributs facultatifs pour noter One-to-One:
inversed-by - Si l'association est bidirectionnelle l'attribut inversed-by doit être spécifié avec le nom du champ sur l'entité inverse qui contient la référence arrière. orphan-removal - Si c'est vrai, l'entité côté inverse est toujours supprimée lorsque l'entité côté propriétaire existe. Par défaut à false. fetch - par défaut LAZY ou EAGER, defaults to LAZY. Cet attribut n'a de sens que sur le côté propriétaire, le côté inverse utilise toujours la stratégie de chargement.
La définition pour le côté propriétaire repose sur un ensemble de défauts de cartographie pour les noms de colonnes à rejoindre. Sans l'élément de la doctrine <join-column/> qui suppose que la clé étrangère soit appellée sur le user_id de l'adresse entités de la table. C'est parce que l'entité Adresse MonProjet est du côté possédant cette association, ce qui signifie qu'il contient la clé étrangère.
La cartographie complété explicitement définie est la suivante:
<entity class= "MyProject\Address"> <one-to-one field= "user" target-entity= "User" inversed-by= "address"> <join-column name= "user_id" referenced-column-name= "id" /> </ One-to-one> </ Entity>
L'association many-to-one est toujours du côté possédant une association bidirectionnelle. Cela simplifie la cartographie comparée à l'association one-to-one. La cartographie minimal pour cette association ressemble à:
<entity class="MyProject\Article"> <many-to-one field="author" target-entity="User" /> </entity>
Les attributs obligatoires:
Attributs optionnels:
Cette définition repose sur un ensembles de défauts de cartographie en ce qui concerne la dénomination de la clé <join-column/>. La cartographie explicitement défini comprend une balise <join-column /> imbriquées à l'intérieur d'une association many-to-one.
<entity class="MyProject\Article"> <many-to-one field="author" target-entity="User"> <join-column name="author_id" referenced-column-name="id" /> </many-to-one> </entity>
Le nom de l'attribut join-column spécifie le nom de la colonne de la clé étrangère et l'attribut referenced-column-name spécifie le nom de la colonne de la clé primaire dans l'entité utilisatrice.
L'association one-to-many est toujours sur le côté inverse de toute association. Il n'existe pas de telle chose comme un uni-directionnel en tête-à-plusieurs, ce qui signifie que cette association existe toujours pour les associations bidirectionnelles.
<entity class="MyProject\User"> <one-to-many field="phonenumbers" target-entity="Phonenumber" mapped-by="user" /> </entity>
Les attributs obligatoires:
Attributs optionnels:
De toutes les associations du many-to-many a la définition la plus complexe. Quand vous comptez sur les valeurs par défaut, vous pouvez omettre la cartographie de nombreuses définitions et comptent sur leurs valeurs implicites.
<entity class="MyProject\User"> <many-to-many field="groups" target-entity="Group" /> </entity>
Les attributs obligatoires:
Attributs optionnels:
Le défaut de cartographie conduirait à une jointure de table avec le nom "GROUPE_UTILISATEUR" en cours de création qui contient deux colonnes "user_id" et "group_id". La définition explicite de cette cartographie serait la suivante:
<entity class="MyProject\User"> <many-to-many field="groups" target-entity="Group"> <join-table name="cms_users_groups"> <join-columns> <join-column name="user_id" referenced-column-name="id"/> </join-columns> <inverse-join-columns> <join-column name="group_id" referenced-column-name="id"/> </inverse-join-columns> </join-table> </many-to-many> </entity>
Voici les deux <join-columns> et étiquettes <inverse-join-columns> nécessaire pour dire à Doctrine de quel côté s'applique la jointure join-colums. Ils sont imbriquées à l'intérieur d'un attribut <join-table /> qui permet de spécifier le nom de la table des many-to-many.
Doctrine permet des opérations en cascade dans un UnitOfWork entre plusieurs entités liées. Vous pouvez spécifier les opérations en cascade dans l'élément <cascade /> interne à l'une des balises mapping de l'association.
<entity class="MyProject\User"> <many-to-many field="groups" target-entity="Group"> <cascade> <cascade-all/> </cascade> </many-to-many> </entity> <src> Outre <cascade-all /> les opérations suivantes peuvent être spécifiées par leurs balises respectives: - <cascade-persist /> - <cascade-merge /> - <cascade-remove /> - <cascade-refresh /> * Élément de colonne Join Pour tout mapping d'association défini explicitement, vous aurez besoin de la balise <join-column />. Il définit comment les clés étrangères et des noms de clef primaire sont appelés pour joindre deux entités. Les attributs obligatoires: - **name** - Le nom de la colonne de la clé étrangère. - **referenced-column-name** - Le nom de colonne de la clé associée des entités primaires Attributs optionnels: - **unique** - Si la colonne de jointure doit contenir une contrainte UNIQUE. Cela n'a de sens pour des join-columns Many-To-Many que pour simuler un unidirectionnelle one-to-many en utilisant un join-table. - **nullable** - devrait être la jointure de colonne nullable, la valeur true. - **on-delete** - action en cascade des clés étrangères à effectuer lorsque l'entité est supprimée, par défaut NO ACTION/RESTRICT mais peut être setté en «CASCADE». * Définissant l'ordre des associations To-Many Vous pouvez exiger que les associations one-to-many ou many-to-many puissent être récupérées en utilisant une clause **ORDER BY** supplémentaires. <src lang="xml"> <entity class="MyProject\User"> <many-to-many field="groups" target-entity="Group"> <order-by> <order-by-field name="name" direction="ASC" /> </order-by> </many-to-many> </entity>
Pour définir des index supplémentaires ou des contraintes d'unicité sur la table des entités, vous pouvez utiliser les éléments <indexes /> et <unique-constraints />.
<entity name="Doctrine\Tests\ORM\Mapping\User" table="cms_users"> <indexes> <index name="name_idx" columns="name"/> <index columns="user_email"/> </indexes> <unique-constraints> <unique-constraint columns="name,user_email" name="search_idx" /> </unique-constraints> </entity>
Vous devez spécifier la colonne et non les noms des champs entité de classe de l'indice et unique-contrainte définitions.
Si la clé primaire d'une entité contient une clé étrangère à une autre entité, on parle d'une relation entité dérivée. Vous pouvez définir cette en XML avec l'attribut «association-key" dans la balise <id>.
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> <entity name="Application\Model\ArticleAttribute"> <id name="article" association-key="true" /> <id name="attribute" type="string" /> <field name="value" type="string" /> <many-to-one field="article" target-entity="Article" inversed-by="attributes" /> <entity> </doctrine-mapping>