Précédent   Forum des professionnels en informatique > PHP > Bibliothèques et frameworks > symfony
symfony Forum d'entraide sur le framework PHP symfony. Avant de poster : cours symfony et FAQ symfony
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 17/02/2011, 16h31   #1
Futur Membre du Club
 
Inscription : février 2009
Messages : 42
Détails du profil
Informations forums :
Inscription : février 2009
Messages : 42
Points : 16
Points : 16
Par défaut Doctrine findOneBy et leftJoin

Salut à tous,

J'ai une classe nommée CorpUserRememberKeyTable par Doctrine qui contient :
Code :
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 :
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
nikolaus est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/02/2011, 19h52   #2
Modérateur
 
Avatar de Michel Rotta
 
Homme Michel Rotta
Responsable d'exploitation informatique
Inscription : septembre 2005
Messages : 4 913
Détails du profil
Informations personnelles :
Nom : Homme Michel Rotta
Âge : 49
Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

Informations professionnelles :
Activité : Responsable d'exploitation informatique
Secteur : Distribution

Informations forums :
Inscription : septembre 2005
Messages : 4 913
Points : 7 505
Points : 7 505
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.
__________________
Si tu donnes un poisson à un homme, il mangera un jour. Si tu lui apprends à pêcher, il mangera toujours (Lao Tseu).
  • Pensez à valoriser les réponses pertinantes, cliquez sur le bouton vert +1 pour indiquer votre accord avec la solution proposée.
  • Pensez à utiliser la balise [code] pour afficher du code, elle est cachée sous le bouton [#] dans l'éditeur.
  • Une discussion est terminée ? Alors le bouton est votre ami !
Michel Rotta est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/02/2011, 21h40   #3
Futur Membre du Club
 
Inscription : février 2009
Messages : 42
Détails du profil
Informations forums :
Inscription : février 2009
Messages : 42
Points : 16
Points : 16
Merci pour ta réponse.

Voici mon schema.yml (en partie)
Code :
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 :
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 :
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 :
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 :
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 :
1
2
3
4
 
// comme ceci :
$user->username
$user->password
Y a-t-il une explication, une meilleure méthode ?

Merci.
nikolaus est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/02/2011, 10h10   #4
Membre chevronné
 
Avatar de Herode
 
Développeur Web
Inscription : mars 2005
Messages : 769
Détails du profil
Informations personnelles :
Localisation : France, Savoie (Rhône Alpes)

Informations professionnelles :
Activité : Développeur Web

Informations forums :
Inscription : mars 2005
Messages : 769
Points : 788
Points : 788
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 :
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 :
$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.
Herode est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 18/02/2011, 10h55   #5
Futur Membre du Club
 
Inscription : février 2009
Messages : 42
Détails du profil
Informations forums :
Inscription : février 2009
Messages : 42
Points : 16
Points : 16
Merci pour ta réponse.

Citation:
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.
nikolaus est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/02/2011, 11h27   #6
Modérateur
 
Avatar de Michel Rotta
 
Homme Michel Rotta
Responsable d'exploitation informatique
Inscription : septembre 2005
Messages : 4 913
Détails du profil
Informations personnelles :
Nom : Homme Michel Rotta
Âge : 49
Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

Informations professionnelles :
Activité : Responsable d'exploitation informatique
Secteur : Distribution

Informations forums :
Inscription : septembre 2005
Messages : 4 913
Points : 7 505
Points : 7 505
En effet, Doctrine hydrate le retour, par défaut, en objet.

Normalement du devrait accéder par :
Code :
$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.
__________________
Si tu donnes un poisson à un homme, il mangera un jour. Si tu lui apprends à pêcher, il mangera toujours (Lao Tseu).
  • Pensez à valoriser les réponses pertinantes, cliquez sur le bouton vert +1 pour indiquer votre accord avec la solution proposée.
  • Pensez à utiliser la balise [code] pour afficher du code, elle est cachée sous le bouton [#] dans l'éditeur.
  • Une discussion est terminée ? Alors le bouton est votre ami !
Michel Rotta est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 18/02/2011, 14h22   #7
Membre chevronné
 
Avatar de Herode
 
Développeur Web
Inscription : mars 2005
Messages : 769
Détails du profil
Informations personnelles :
Localisation : France, Savoie (Rhône Alpes)

Informations professionnelles :
Activité : Développeur Web

Informations forums :
Inscription : mars 2005
Messages : 769
Points : 788
Points : 788
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 :
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
Herode est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 18/02/2011, 16h03   #8
Futur Membre du Club
 
Inscription : février 2009
Messages : 42
Détails du profil
Informations forums :
Inscription : février 2009
Messages : 42
Points : 16
Points : 16
@Herode
Génial, bien compris.

@Michel Rotta
Oui ça marche aussi, et c'est plus joli...
Merci

nikolaus est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 12h21.


 
 
 
 
Partenaires

Hébergement Web