IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

ORM PHP Discussion :

[Doctrine] "Methodes relationnels" inexistantes dans le modèle


Sujet :

ORM PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    13
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Belgique

    Informations forums :
    Inscription : Juillet 2008
    Messages : 13
    Par défaut [Doctrine] "Methodes relationnels" inexistantes dans le modèle
    Bonjour,

    Je me lance depuis peu dans Symfony dans le but de développer une plateforme web permettant à ma mère de gérer les lectures de ses élèves. J'ai parcouru pas mal la documentation, et tente d'appliquer les différents concepts. J'en suis à la création de la base de données, et à l'utilisation des modèles générés. Voici mon problème, avec un schema simplifié :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
     
    Book:
      tableName: book
      actAs:
        Timestampable: ~
      columns:
        serial: { type: string(20), notnull: true, unique: true }
     
    Reader:
      tableName: reader
      actAs:
        Timestampable: ~
      columns:
        serial: { type: string(20), notnull: true, unique: true }
      relations:
        Books:
          class: Book
          refClass: BookReader
          local: id
          foreign: book_id
          foreignAlias: Readers
     
    BookReader:
      tableName: book_reader
      actAs:
        Timestampable: ~
      options:
        symfony:    { form: false, filter: false }
      columns:
        book_id:    { type: integer, primary: true }
        reader_id:  { type: integer, primary: true }
      relations:
        Book:       { local: book_id, foreign: id, foreignAlias: BookReaders }
        Reader:     { local: reader_id, foreign: id, foreignAlias: BookReaders }
    La génération via ./symfony doctrine:bla-bla génère bien l'ensemble des modèles, j'ai aussi chargé des données dans les tables, histoire de pouvoir tester ces modèles avant de rendre plus complexe ma BDD.

    Là où je bloque, c'est que je souhaiterais récupérer, pour un livre identifié par son serial, tous les lecteurs. Selon ce que j'ai pu lire (mais j'ai surement mal compris un concept), lorsqu'on établi des relations dans le schema de la BDD, certaines fonctions sont générées automatiquement, c'est pourquoi, je pensais que le code suivant fonctionnerait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
        $q = Doctrine_Core::getTable('Book')
          ->createQuery('b')
          ->where('b.serial = ?', $this->serial);
        $book = $q->execute();
     
        $this->readers = $book->getReaders();
    Vous vous en doutez, ça ne fonctionne pas, et j'ai l'erreur suivante (assez claire) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Fatal error: Call to undefined method Doctrine_Collection::getReaders() in [...]
    Est-ce que cette fonction n'aurait pas du être générer, à la vue de la relation n-n entre ces deux tables ? C'est ce que j'attendais comme behavior lorsque j'ai lu cette idée dans l'introduction à Symfony (http://www.symfony-project.org/gentl...elated_records).

    Merci d'avance pour votre aide !

  2. #2
    Membre chevronné
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    396
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 396
    Par défaut
    Je n'ai pas lu tout le code de ton modèle mais :
    - ta relation getReaders ne peut s'appliquer que sur un objet Book. Ici, tu l'appliques sur une Doctrine_Collection (qui est une collection de Books), ce qui explique ton message d'erreur ;
    - la méthode ->execute permet de retourner tous les éléments de ta DB qui vérifient tes conditions (addWhere). Tous ces éléments sont stockés dans une Doctrine_Collection.

    Du coup, ce que tu veux toi, c'est juste le seul élément vérifiant cette condition, ce qui se fait par un fetchOne() :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $book = Doctrine_Core::getTable('Book')
          ->createQuery('b')
          ->where('b.serial = ?', $this->serial)
          ->fetchOne();
    Ou de façon plus concise :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $book = Doctrine_Core::getTable('Book')
          ->findOneBySerial($this->serial);
    Les méthodes findOneBy*, findAllBy* sont des méthodes magiques.
    Si tu voulais ajouter d'autres conditions par rapport à tes champs, il suffirait de faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ->findOneBySerialAndNameAndValue($serial, "toto", "0");
    Courageux de prendre en main un framework pour faire une appli à sa mère
    Vue l'appli, n'aurais-tu pas pu passer plutôt par un CMS ?

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    13
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Belgique

    Informations forums :
    Inscription : Juillet 2008
    Messages : 13
    Par défaut
    Tout bon !

    Je n'avais pas encore pris connaissances de telles fonctions. Faut croire que je n'ai pas encore tout lu sur Doctrine (ce qui effectivement le cas ).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
        $book = Doctrine_Core::getTable('Book')
          ->findOneBySerial($this->serial);
     
        $this->readers = $book->getReaders();
    J'aurais pu voir plus loin que le bout de mon nez.. Collection.. Idiot que je suis =))

    Sinon, clairement, un CMS aurait surement suffit, mais je compte développer d'autres choses par la suite, et prendre un main un framework tel que Symfony pour un projet de base me semblait une bonne idée, au lieu de refaire Jobeet

    Une dernière question : où est-ce que la méthode getReaders() est-elle définie ? Créer à la volée (virtuelle) ? Ou se retrouve-t-elle dans un fichier ?

    Merci pour avoir pointer mon problème en tout cas, très certainement un gain de temps pour la suite.

  4. #4
    Membre chevronné
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    396
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 396
    Par défaut
    Si tu veux lire tout Doctrine, voici ce qu'il te faut : http://www.doctrine-project.org/proj...ntroduction/zh
    Je ne me suis lancé dans sa lecture que ce temps-ci, j'ai moi aussi encore beaucoup de choses à découvrir
    Ceci dit, je te recommande vivement la lecture des chapitres de base : ils regorgent d'informations qui peuvent te faire gagner beaucoup de temps !

    Sinon, pour la méthode getReaders(), elle est résolue à la volée par Doctrine_Table. Tu peux aller voir le code pour info, mais je ne suis pas sûr que ce soit essentiel.

  5. #5
    Expert confirmé
    Avatar de Michel Rotta
    Homme Profil pro
    DPO
    Inscrit en
    Septembre 2005
    Messages
    4 954
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : DPO
    Secteur : Distribution

    Informations forums :
    Inscription : Septembre 2005
    Messages : 4 954
    Par défaut
    Citation Envoyé par bdcstr Voir le message
    Une dernière question : où est-ce que la méthode getReaders() est-elle définie ? Créer à la volée (virtuelle) ? Ou se retrouve-t-elle dans un fichier ?

    C'est toi qui l'a définie (un peu indirectement) dans ton modèle (shema.yml).

    En effets tu as :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    Reader:
      ...
      relations:
        Books:
          ...
          foreignAlias: Readers
    C'est le Readers défini derrière le "foreignAlias" qui va générer la méthode getReaders(). De la même manière, sur la table Reader tu as une méthode getBooks().

    A noter que la définition ainsi parfaitement mise en œuvre dans ton schéma de la relation 1-n permet de ce passer totalement de la table intermédiaire.

    Tu peux aussi envisager de récupérer tous les noms des livres des élèves donc le nom commence par un "B".
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    $q = Doctrine_query::create()
                 ->form('Reader r')
                 ->leftjoin('r.Books b')
                 ->where('r.name like ?', 'b*');
    $q->execute()
    En supposant que la table Reader aie un champ nom.

    Avantage, une seul requête.

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    13
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Belgique

    Informations forums :
    Inscription : Juillet 2008
    Messages : 13
    Par défaut
    C'est le Readers défini derrière le "foreignAlias" qui va générer la méthode getReaders(). De la même manière, sur la table Reader tu as une méthode getBooks().
    Grâce au nom de la relation j'imagine (relations: { Books: { ... } }) ?

    A noter que la définition ainsi parfaitement mise en œuvre dans ton schéma de la relation 1-n permet de ce passer totalement de la table intermédiaire.
    Si je comprends bien ce que tu dis, sans définir BookReader, j'aurais toujours ma relation n-n : Un livre est lu par plusieurs lecteurs, et un lecteur a lu plusieurs livres ? De toute manière, dans ce cas-ci, j'ai besoin de cette table intermédiaire pour les dates d'insertions (Timestampable), mais cette non-nécessité (sous la condition d'avoir correctement compris ton message) pourrait-être intéressante pour alléger mon schema lorsque je n'ai besoin de rien d'autres que d'une relation n-n. (Merci de confirmer si j'ai bien compris ou pas.. ).

    Faudra que je m'intéresse au fonctionnement des JOIN en Doctrine ;D Pas encore eu l'utilité de cela, mais ça ne serait tarder !

  7. #7
    Membre chevronné
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    396
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 396
    Par défaut
    Petit lien concernant les relations n-n (qui nécessitent une table d'association) :
    Relationships many-to-many (site de Doctrine)

+ Répondre à la discussion
Cette discussion est résolue.

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo