Navigation

Related Articles

Back to Latest Articles

Tips : Symfony 1.3/1.4 orderBy des relations


Olivier
Tips : Symfony 1.3/1.4 orderBy des relations

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

Show Comments (4)

Comments

  • CpnForTehWin

    Merci pour cette petite astuce !

    • Article Author
  • Axan

    Celà ne fonctionne pas (chez moi du moins), le champ ‘orderBy’ n’est pas pris en compte à la génération depuis le YML.
    En revanche j’ai trouvé un autre moyen de faire:
    Surcharger la méthode "construct()" de la classe xxxTable
    comme ceci
    [code]
    function construct()
    {
    setOption(‘orderBy’, ‘leChamp DESC’);
    }
    [/code]

    Il faut bien surcharger construct() et non __construct() !

    • Article Author
  • ipatate

    nickel la method construct, pour obtenir l’order dans les select !!

    • Article Author
  • DonE

    Lorsque je surcharge ‘construct()’ ma requête inclus en double la colonne à trier, exemple :

    SELECT abc, def, ghi FROM table ORDER BY abc ASC, abc ASC

    Si je consulte le contenu de l’option « orderBy’ avant de faire le « setOption » j’obtiens un vide.

    Si je consulte le contenu de l’option « orderBy’ après le « setOption » j’obtiens la bonne valeur, soit une seule fois la colonne triée.

    Enviro = sf1.4.4, Doctrine 1.2.2, MSSQL 2005

    Des suggestions?

    Merci pour votre aide

    • Article Author

Recevez nos articles