Tips : Symfony 1.3/1.4 orderBy des relations

14.01.2010  • Samuel Breton

Depuis la branche 1.3/1.4 la gestion des relations a été bien enrichie.

Au niveau des formulaire l’apparition du EmbedRelation a vraiment facilité l’implémentation des embedForm. Je ne vais pas reprendre l’explication de cette fonctionnalité dans cet article et vous renvoie donc vers le très bon article de NiKo sur son blog (En anglais).

Petit problème, l’ordre de tri de la Doctrine_Collection retrounée qui est … en vrac ^^ J’en ai fait l’expérience sur une base postGre ou l’ordre de retour est en fonction de la dernière modification alors que sur une base mySql c’est l’ordre des IDs (déjà moins gênant). Dans les 2 cas ça n’est pas très satisfaisant, et on aimerais pouvoir maitriser l’ordre de tri de cette relation.

Un bout de schema.yml pour pouvoir illustrer mon explication :

...
Produit:
  columns:
    id:                 { type: integer(4), unsigned: true, primary: true, autoincrement: true }
    name:               { type: string(128), notnull: true }
 
Photo:
  columns:
    id:                 { type: integer(4), unsigned: true, primary: true, autoincrement: true }
    file_name:          { type: string(128), notnull: true }
    id_produit:         { type: integer(4), unsigned: true }
    ordre:              { type: integer(4), unsigned: true }
  relations:
    Produit:
      local:            id_produit
      foreign:          id
      foreignAlias:     Photos
      onDelete:         CASCADE
...

Dans ce contexte on peut imaginer faire un EmbedRelation des Photos dans la classe ProduitForm.

Le fonctionnement du EmbedRelation est qu’il utilise l’accesseur magique getPhotos() qui elle même fait un findByIdProduit() dans la classe PhotoTable et retourne une Doctrine_Collection d’objects Photo. Seul problème comme je l’ai dit plus haut, c’est que la requête n’est pas trié.

Vous allez me dire “c’est facile, il n’y a qu’à surcharger getPhotos() de Produit.class.php”. C’est ce que j’avais fait au début, et ça marche. Seul problème, c’est que lorsque l’on redéfini un accesseur magique (ici le getteur) l’autre (le setteur) ne fonctionne plus… est ce que c’est voulu ou est ce que c’est un bug? Je n’en sais rien ^^ Toujours est-il que je me servais du setteur et donc cette solution ne m’a pas convenu et j’ai cherché une alternative.

L’alternative est prévue par Doctrine qui depuis la 1.2 qui implémente la possibilité de spécifier le orderBy sur une relation directement lors de sa définition dans le schema.yml. Seul problème le foreinOrderBy n’existe pas et donc la définition de la relation ne peut plus se faire comme je l’avais écrite plus haut, il faut la définir des deux cotés.

Tréve de blabla, ca ressemble à quelque chose comme ca :

...
Produit:
  columns:
    id:                 { type: integer(4), unsigned: true, primary: true, autoincrement: true }
    name:               { type: string(128), notnull: true }
  relations:
    Photos:
      type:             many
      class:            Photo
      local:            id
      foreign:          id_produit
      orderBy:          ordre ASC
      onDelete:         CASCADE
 
Photo:
  columns:
    id:                 { type: integer(4), unsigned: true, primary: true, autoincrement: true }
    file_name:          { type: string(128), notnull: true }
    id_produit:         { type: integer(4), unsigned: true }
    ordre:              { type: integer(4), unsigned: true }
  relations:
    Produit:
      local:            id_produit
      foreign:          id
      onDelete:         CASCADE
...

J’espère que cette petite astuce vous aidera.
@bientôt

Directeur conseil chez Spiriit
J'accompagne nos clients sur la mise en place de la stratégie, de l'architecture et dans la structuration du projet. J'interviens en amont des projets pour la planification et en aval sur la partie KPI / Performance.
Voir l’étude de cas
Lire l’article
Lire l’actualité
En savoir plus
En savoir plus
Voir le témoignage
Fermer