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

Symfony PHP Discussion :

Doctrine findOneBy et leftJoin [1.x]


Sujet :

Symfony PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Février 2009
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 42
    Par défaut Doctrine findOneBy et leftJoin
    Salut à tous,

    J'ai une classe nommée CorpUserRememberKeyTable par Doctrine qui contient :
    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
     
    <?php
     
       public static function getInstance()
       {
           return Doctrine_Core::getTable('CorpUserRememberKey');
       }
     
       public function myFindOneByRememberKey($remember_key)
       {
         $q = $this->createQuery('rk')
           ->leftJoin('rk.CorpUser u')
           ->andWhere('rk.rememeber_key = ?', $remember_key)
           ->andWhere('u.is_activated = ?', true);
         return $q->fetchOne();
       }

    et dans apps/frontend/lib/myUser.class.php
    j'ai :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    <?php
     
    $user = Doctrine_Core::getTable('CorpUserRememberKey')->myFindOneByRememberKey($remember_key);
     
    foreach($user as $key => $value)
    {
         echo ' $user->'.$key.' : '.$value.'<br />';
    }
    L'objet $user n'est pas "hydraté" par les valeurs de la table CorpUser mais seulement par celles de la table CorpUserRememberKey. Je voudrai avoir accès aux valeurs (getters) des deux tables jointes. Comment faire ?

    Thx

  2. #2
    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
    Quel est la table CorpUser ?
    Quel sont les deux structures ?
    Quel sont leurs relations ?

    As-tu pensé à aller voir du côté des plugins ? Dans la salle plugin de symfony tu as un sujet épinglé avec la liste des plugins les plus utilisés ici dont notamment sfDoctrineGuard qui gère tous l'aspect sécurité, user et droits. Je pense qu'avant de partir sur un code propriétaire tu aurais intérêt à y jeter un œil.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Février 2009
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 42
    Par défaut
    Merci pour ta réponse.

    Voici mon schema.yml (en partie)
    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
     
    CorpUser:
      actAs: [Timestampable]
      tableName: corp_user_user
      columns:
        id: { type: integer, primary: true, autoincrement: true }
        username: { type: string(255), unique: true, notnull: true }
        password: { type: string(40), notnull: true } # sha1
        email: { type: string(255), notnull: true }
        avatar: string(255)
        is_super_admin: { type: boolean, notnull: true, default: 0 }
        is_activated: { type: boolean, notnull: true, default: 0 }
        last_login: { type: timestamp }
     
    CorpUserRememberKey:
      tableName: corp_user_remember_key
      columns:
        user_id: { type: integer, notnull: true }
        remember_key : { type: string(40), notnull: true } # sha1
        expires_at:   { type: timestamp, notnull: true }
      relations:
        CorpUser:
          foreignAlias: User
          local: user_id
          foreign: id
    J'ai essayé sfDoctrineGuardPlugin, mais j'ai envie d'apprendre symfony en profondeur, je ne suis pas sur un projet réel, je fais mes armes.
    Je n'avais pas vu cet article, je vais voir, merci.

    J'ai plus ou moins résolu mon problème, mais j'observe une bizarrerie (selon moi):
    j'ai ça dans la classe CorpUserTable:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    public function findOneByRememberKey($remember_key)
    {
          $q = Doctrine_Query::create()
            ->select('rk.*, u.*')
            ->from('CorpUserRememberKey rk')
            ->leftJoin('rk.CorpUser u')
            ->andWhere('rk.remember_key = ?', $remember_key)
            ->andWhere('u.is_activated = ?', true);
          return $q->fetchOne();
     
    }

    Je l'appelle dans myUser.class.php :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    $user = Doctrine_Core::getTable('CorpUser')->findOneByRememberKey($remember_key);
    et j'observe que j'ai accès au éléments de la table CorpUserRememberKey ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    $user->remember_key
    $user->expires_at
    etc.
    alors que pour la table jointe (CorpUser), j'accède aux éléments seulement de cette façon
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    $user->CorpUser->username
    $user->CorpUser->password

    Alors que je m'attendais comme en pur PHP à avoir accès à tous les élements des 2 tables de la même façon...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    // comme ceci :
    $user->username
    $user->password
    Y a-t-il une explication, une meilleure méthode ?

    Merci.

  4. #4
    Membre émérite Avatar de Herode
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2005
    Messages
    825
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2005
    Messages : 825
    Par défaut
    Je ne sais pas ce que tu veux dire par 'pur PHP' mais en POO, c'est plutôt le contraire qui me paraitrait étonnant et fautif.

    Ta table principale est CorpsUserRememberKey, l'objet associé a un accès direct à ses colonnes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $user->rememberKey
    $user->corpsUserId
    Par commodité, Doctrine crée et hydrate un objet CorpsUser correspondant à la clé étrangère :
    et cet objet a à son tour accès à ses colonnes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $user->CorpsUser->username
    Ce qui serait fautif, c'est de confondre $user->CorpsUser->username et $user->username

    Bien sûr, rien ne t'empêche d'ajouter un proxy dans CorpsUserRememberKey pour accéder directement au username qui t'intéresse.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Février 2009
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 42
    Par défaut
    Merci pour ta réponse.

    Je ne sais pas ce que tu veux dire par 'pur PHP'
    J'entends hors de symfony et surtout de Doctrine.
    Même en passant par PDO, quand je fais une requête sur 2 tables jointes, en demandant un array ou un objet, j'ai accès à tous les éléments voulus sur le même niveau, d'où ma surprise...
    Mais c'est sans doute à cause d'un défaut de "bonne pratique" ?

    La manière de faire de Doctrine est effectivement bien meilleure. Il suffisait de la connaître, j'ai rien trouvé de très explicite dans la doc.

  6. #6
    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
    En effet, Doctrine hydrate le retour, par défaut, en objet.

    Normalement du devrait accéder par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $user->getCorpsUser()->getUsername()
    qui est la syntaxe normal en objet.

    Tu as le possibilité de changer l'hydratation (cf documentation doctrine sur l'hydratation) et de récupérer un tableau plat comme en "php pure". Hydrater sur un array plat ou hiérarchique en fonction de tes besoins présente l'avantage d'être plus rapide et moins lourd en mémoire. Par contre tu perds la liaison avec le modèle objet et donc toutes les fonctionnalités qui vont avec, notamment la partie modification et sauvegarde des données.

    Ton schema est correcte et pour une fois je n'ai rien à y redire.

    Je pense malgré tous que, pour ta formation personnel, il serait intéressant, après avoir cherché et fais fonctionner ton système, d'explorer la manière dont sfDoctrineGuardPlugin procédé je suis sur que cela ne peut qu'être instructif. Vu le nombre de sites qui l'exploite, cela ne doit pas être complètement nul.

  7. #7
    Membre émérite Avatar de Herode
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2005
    Messages
    825
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2005
    Messages : 825
    Par défaut
    Citation Envoyé par nikolaus Voir le message
    Même en passant par PDO, quand je fais une requête sur 2 tables jointes, en demandant un array ou un objet, j'ai accès à tous les éléments voulus sur le même niveau, d'où ma surprise...
    Mais c'est sans doute à cause d'un défaut de "bonne pratique" ?
    OK, je n'avais pas fait le rapprochement avec l'approche PDO. Je ne verrai pas cela comme un défaut de bonne pratique dans PDO mais comme lié au fait que les objets PDO et les objets Doctrine ne représentent pas la même chose.

    Pour autant que je sache, un objet PDO obtenu après requête encapsule une ligne de résultats tandis qu'un objet Doctrine encapsule une instance (complète) de ton modèle conceptuel. Pour PDO, c'est un peu l'équivalent de ce que l'on a en appelant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $res = mysql_query("select * from bidule join truc on etc...");
    $obj = mysql_fetch_object($res);
    C'est correct tant que l'objet ne représente rien d'autre qu'un tableau "amélioré" mais les choses se compliquent pour le développeur quand on a plusieurs niveaux de jointures. Par exemple, un Utilisateur ayant plusieurs Adresses et pour chaque adresse plusieurs NumérosDeTéléphone. Un accès du type $user->telephone ne fonctionne pas dans ce cas.

    Doctrine résoud ce problème en faisant son travail d'ORM, il te fournit donc un objet Utilisateur complet dans lequel est accessible la liste de ses Adresses, chaque Adresse est elle-même un objet qui donne accès à ses NumérosDeTéléphone et tu enrichis tes classes à ta sauce avec toute méthode te semblant utile.

    La "bonne pratique" dépend donc du contexte et de la sémantique des entités manipulées.

    Et en effet, la doc de Symfony est... hum... améliorable

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

Discussions similaires

  1. [Doctrine] Demande d'information sur une bonne utilisation
    Par anaon dans le forum Bibliothèques et frameworks
    Réponses: 1
    Dernier message: 27/02/2009, 12h25
  2. [Doctrine] fixture et table liée
    Par nicolas.pied dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 13/02/2009, 12h16
  3. [Doctrine] classe d'association et récursivité
    Par Mitaka dans le forum PHP & Base de données
    Réponses: 5
    Dernier message: 21/05/2008, 17h13
  4. [Doctrine] Mettre doctrine en prod
    Par hpavavar dans le forum Bibliothèques et frameworks
    Réponses: 2
    Dernier message: 28/01/2008, 21h27
  5. [Doctrine] problème de case sensitive
    Par yanice dans le forum Bibliothèques et frameworks
    Réponses: 3
    Dernier message: 27/10/2007, 12h15

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