Générer ses Modèles de class avec l'ORM propel & symfony2 dans des sous répertoires

Afin de mieux organiser son code dans symfony2 et notamment dans ses class, je chercherais sur la doc comment générer mes model de table dans des sous répertoires. Hélas la doc est un peu limite là dessus, ils ne montrent pas vraiment comment le mettre en place et c'est assez disparate. J'ai cherché sur google et tout les sites ricains, mais rien !

Après avoir fait quelques tests qui ont échoué et modifié pas mal de choses, j'ai enfin réussi à générer mes class de modèle avec propel dans symfony2, en les organisant dans des répertoires ainsi que leur namespace en adéquation. Et oui, Imaginez que vous deviez faire du reverse engineering sur une 100ène de table ??? Et encore 100 je suis gentil, j'avais du le faire sur une base ayant 380 table et il y a des applications php qui en ont plus.

Tagger votre schema.xml de base de donnée avec package et namespace

Avant tout vous devez générer le mapping de votre base de donnée ! Heureusement propel va le faire pour nous. Dans votre console ou terminal sous Symfony2, tapez la commande : $ app/console propel:reverse

Propel va générer un fichier xml du nom de : default_reversed_schema.xml situé dans votre répertoire de symfony2 : app/propel/generated-schemas/

Ceci est le schéma représentatif de votre base de donnée. Copiez le et créez un fichier schema.xml dans l'emplacement de votre Bundle désiré.

Si comme moi vous avez un Bundle qui va vous servir comme Bundle de Core de toute votre application, ce qui est le mieux lorsque l'on veut avoir "Un" Model unique de base pour toutes les requêtes classiques de votre base de donnée, important si vous travaillez à plusieurs développeur sur plusieurs bundle différent, comme ça cela permettra de factoriser au mieux votre Model de class qui vont requêter à la base de donnée. "Sous Doctrine ce sont les Entités".

Et copiez le contenu de votre fichier default_reversed_schema.xml ou bien dupliquez le et changer le nom.

Hiérarchisez vos classes models de Propel sous Symfony2

Comme dit plus haut, si vous avez beaucoup de table dans votre base de donnée, il est préférable d'avoir chaque class représentative de vos tables, répartie dans des Dossiers. C'est bien plus pratique et lisible pour s'y retrouver plutôt que de devoir scroller tout vos modèles afin de trouver le bon.

  1. Ouvrez donc votre fichier schema.xml dans votre bundle.
  2. Il va falloir ajouter des tags sur les segments "database" et "table" de votre fichier xml
  3. votre fichier se présente comme ci-dessous
<database name="default" defaultIdMethod="native">
  <table name="article" phpName="Article" idMethod="native">
    <column name="id" phpName="Id" type="INTEGER" primaryKey="true" autoIncrement="true" required="true"/>
    <column name="date" phpName="Date" type="TIMESTAMP" required="true"/>
    <column name="titre" phpName="Titre" type="VARCHAR" size="255" required="true"/>
    <column name="auteur" phpName="Auteur" type="VARCHAR" size="255" required="true"/>
    <column name="contenu" phpName="Contenu" type="CLOB" required="true"/>
    <column name="image_id" phpName="ImageId" type="INTEGER" required="false"/>
    <foreign-key foreignTable="image" name="FK_CD8737FA3DA5256D" onDelete="RESTRICT" onUpdate="RESTRICT">
      <reference local="image_id" foreign="id"/>
    </foreign-key>
    <unique name="UNIQ_CD8737FA3DA5256D">
      <unique-column name="image_id"/>
    </unique>
    <vendor type="mysql">
      <parameter name="Engine" value="InnoDB"/>
    </vendor>
  </table>
......
  1. Ajoutez à la ligne <database le tag : namespace="Le\Namespace\a\vous"

Ceci va servir pour générer le "namespace" de base de votre dossier "Model" donc c'est très important pour qu'il n'y ait pas de conflit de class mais surtout, que ça fonctionne !

  1. Il faut ensuite ajouter le tag = "package" Et oui c'est ce mot clé qui va permettre à propel de savoir où placer votre code et créer votre dossier spécifique à la class !!

Ecrivez le comme ceci, toujours dans la balise <database... package="src.schemindevotrebundle.model".

+Exemple concret pour la bonne syntaxe :+

namespace="Winapp\BlogBundle\Model" package="src.Winapp.BlogBundle.Model"

Ensuite il vous faut aussi ajouter le namespace et le chemin du package pour chaque balise <table> ca c'est chiant !! J'aurais pensée qu'il suffisait d'ajouter le nom du namespace tout simplement et que propel en déduirait automatiquement mais il semble que non.

Faite le comme sur l'exemple ci-dessous :

<database name="default" namespace="Winapp\BlogBundle\Model" defaultIdMethod="native" package="src.Winapp.BlogBundle.Model">
  <table name="article" phpName="Article" idMethod="native" namespace="Article" package="src.Winapp.BlogBundle.Model.Article">
    <column name="id" phpName="Id" type="INTEGER" primaryKey="true" autoIncrement="true" required="true"/>
    <column name="date" phpName="Date" type="TIMESTAMP" required="true"/>
    <column name="titre" phpName="Titre" type="VARCHAR" size="255" required="true"/>
    <column name="auteur" phpName="Auteur" type="VARCHAR" size="255" required="true"/>
    <column name="contenu" phpName="Contenu" type="CLOB" required="true"/>
    <column name="image_id" phpName="ImageId" type="INTEGER" required="false"/>
    <foreign-key foreignTable="image" name="FK_CD8737FA3DA5256D" onDelete="RESTRICT" onUpdate="RESTRICT">
      <reference local="image_id" foreign="id"/>
    </foreign-key>
    <unique name="UNIQ_CD8737FA3DA5256D">
      <unique-column name="image_id"/>
    </unique>
    <vendor type="mysql">
      <parameter name="Engine" value="InnoDB"/>
    </vendor>
  </table>

La vous remarquerez que le namespace de la table est simplement le nom de votre table en CamelCase ? C'est normal car propel va encapsuler le namespace et l'ajouter à la fin du namespace qui se trouve dans la balise <database>. N'oubliez pas le tag package="" très important ! Afin de créer le dossier adéquate.

Maintenant Générons nos classes de model !

Tapez dans votre console la commande : $ app/console propel:model:build

Et hop ! Vous pouvez regardez dans le répertoire du bundle que vous aurez déclaré dans votre schema.xml et toutes vos classes auront été créé et rangé au bon endroit !

C'est quand même mieux non ?

J'espère que ça en aidera plus d'un qui souhaite travailler avec Propel.