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 :

Problème de récupération d'objet action AJAX [1.x]


Sujet :

Symfony PHP

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 9
    Points : 7
    Points
    7
    Par défaut Problème de récupération d'objet action AJAX
    Bonsoir à tous

    Voici mon problème :

    Au clic sur un lien je lance une requête AJAX (via jQuery load) pour recharger un élément DOM (jusqu'à là tout va bien).

    L'action symfony appelé doit mettre à jour l'enregistrement de la table relié au module, insérer un enregistrement dans une autre table et enfin récupérer les informations nécessaires pour l'affichage dans la vue associé.

    Voici la fonction de mon fichier action :
    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
    35
    36
    37
    38
    39
    40
    41
    42
     
    public function executeEncherir(sfWebRequest $request)
      {
    	  //CONTROLE CONNEXION
    	if($this->getUser()->isAuthenticated()){
    		//RECUP INFO CLIENT
    		$this->client = Doctrine::getTable('Client')->find(array($this->getUser()->getAttribute('id')));
    		//CONTROLE CREDIT
    		if($this->client->getCredit()>0){
    			//RECUP INFO ENCHERE
    			$this->enchere_clic = Doctrine_Query::create()
    			  ->from('EnchereClic c')
    			  ->leftJoin('c.EnchereCout o')
    			  ->leftJoin('c.EnchereDuree p')
    			  ->where('c.id = ?',$request->getParameter('id'))
    			  ->execute();
    			//CREATION HISTORIQUE
    			$this->enchereClicHisto=new enchereClicHisto();
    			$this->enchereClicHisto->setClientId($this->getUser()->getAttribute('id'));
    			$this->enchereClicHisto->setEnchereClicId($request->getParameter('id'));
    			$this->enchereClicHisto->setNbCredit($this->enchere_clic->EnchereCout->getCout());
    			$this->enchereClicHisto->save();
    			//MAJ DT FIN ENCHERE
    			$dtFin=$this->enchere_clic->getDtFin();
    			$dtFin=str_replace('-',':',$dtFin);
    			$dtFin=strtotime($dtFin);
    			$dtFin = date("Y-m-d h:i:s",$dtFin+$this->enchere_clic->EnchereDuree->getDuree());
    			$this->enchere_clic->setDtFin($dtFin);
    			$this->enchere_clic->save();
    			//RECUP PRIX
    			$this->enchere_clic2 = Doctrine_Query::create()
    			  ->select('COUNT(c.id) as prix')
    			  ->from('EnchereClicHisto c')
    			  ->where('c.enchere_clic_id = ?',$request->getParameter('id'))
    			  ->execute();
    		}else{
    		//TODO l'UTILISATEUR N'A PLUS DE CREDIT	
    		}
    	}else{
    		//TODO L'UTILISATEUR DOIT SE CONNECTEZ OU SINSCRIRE
    	}
      }
    Le problème c'est que j'ai cette erreur qui s'affiche lors de la recupération des valeur dans mes tables liés (left join) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Fatal error: Call to undefined method Doctrine_Collection::getCout() in /home/sfproject/bigenchere/apps/frontend/modules/enchereclic/actions/actions.class.php on line 88
    Je pense que ma méthode de récupération de l'élément "enchère_clic" n'est pas la bonne (car ma requête me semble valide).

    Est t'il possible de récupérer des enregistrement en utilisant un objet ( ex : $this->enchereClic=new enchereClic() ) plutôt qu'une requête doctrine si oui comment faire pour utiliser cette méthode ??

    Peut être que je devrais créer une/des fonction(s) dans le(s) modèle(s) ??

    je suis débutant en symfony et certaine notions du MVC sont encore un peu flou à mes yeux.

    Merci d'avance

  2. #2
    Expert éminent
    Avatar de Michel Rotta
    Homme Profil pro
    DPO
    Inscrit en
    Septembre 2005
    Messages
    4 954
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    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
    Points : 8 486
    Points
    8 486
    Par défaut
    As-tu pris le temps de parcourir le tutoriel JobeetJob ? Si non, je te recommande fortement de prendre une vingtaine d'heure pour le parcourir attentivement, tu y trouveras les réponses à la majorité de tes questions.

    J'aime le message d'erreur, mais quel est la ligne 88 ?

    Une partie du code pourrait effectivement être avantageusement transférer dans modèle plutôt que dans le contrôleur.

    Tu aurais probablement intérêt à utiliser le plugin sfDoctrineGuardUserPlugin pour ta gestion d'utilisateur. A utiliser un droit plutôt qu'une simple 'est connecté' pour ta sécurité, transférer la sécurité sans le fichier security.yml.

    J'ai un peu de mal entre les enchere_clic, enchere_clic2 et enchereClicHisto.

    Les variables sus citées me semble propre à la méthode, dont on devrait pouvoir se passer du $this-> qui les remontent au niveau de l'objet.
    Tu peux écrire le code en continu
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    $this->enchereClicHisto=new enchereClicHisto();
    $this->enchereClicHisto->
         setClientId($this->getUser()->getAttribute('id'))->
         setEnchereClicId($request->getParameter('id'))->
         setNbCredit($this->enchere_clic->EnchereCout->getCout())->
    save();
    Il y a encore pas mal de petits trucs "louche" mais on va traité petit à petit.

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 9
    Points : 7
    Points
    7
    Par défaut
    J'ai bien suivi le tuto jobeet (quasiment en entier sauf la recherche et la partie API qui ne me sont pas utile pour l'instant) mais malgré sa je rame encore dans certain cas un peu plus complexe que les cas développer dans jobeet (lorsque les actions gère plusieurs tables).

    Pour l'utilisateur j'utilise déjà sfDoctrineGuardUserPlugin mais seulement pour l'admin.
    Pour le front je n'est pas besoin de niveau d'utilisateur ni de groupe etc... un compte basique est suffisant (mais a l'avenir j'utiliserais le plugin même en front mais la partie compte utilisateur du site est terminé donc je vais surement resté comme cela pour l'instant).

    La ligne 88 est la ligne suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    $this->enchereClicHisto->setNbCredit($this->enchere_clic->EnchereCout->getCout());

    Explicatif de la problématique générale du module :

    Le système à mettre en place est un système d'enchère au centime (le prix de l'article commence a 0.00€ à chaque enchère (le prix d'une enchère peut varier 1,2,3... crédit(s)) le prix monte de 0.01€ et la date de fin de l'enchère augmente de X secondes) lorsque l'enchère est terminé (date fin) le dernier à avoir enchéri remporte l'article.

    Lorsqu'une enchère est créer (en admin seulement) elle est lié à un article (pas dans le shéma ci dessous car pas utile pour cette action) elle a une date de début, une date de fin, un cout (le nombre de crédits à utiliser pour enchérir) , une durée de relance (le nombre de seconde que l'on rajoute a la date de fin de l'enchère).

    Les différents couts et durées possible sont contenu dans des tables séparés (gestion plus simple pour l'admin).

    Lorsqu'un utilisateur enchéri je doit donc ajouter le nombre de seconde (contenu dans la table enchere_duree) à la date de fin (table enchere_clic), créer un enregistrement dans la table enchere_clic_histo (historique de toutes les enchères) et retourner à ma vue le prix actuel de l'enchère en centime (le nombre d'enregistrement dans l'historique pour cette enchère) ainsi que le login de la personne qui vient d'encherir (l'utilisateur qui a la main sur l'enchère).


    Voici le shéma pour les Tables enchere_clic, enchere_cout, enchere_duree et enchere_clic_histo.

    Et l'adresse du site en dev : http://preprod3.noobi.fr/frontend_dev.php/
    Vous ne pourrez pas tester car il faut un compte utilisateur et des crédits pour pouvoir enchérir (si pas de compte ou pas de crédits ces cas seront géré dans les parties "TODO" de la fonction cité dans le message précédent).


    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
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
     
    EnchereClic:
      connection: doctrine
      tableName: enchere_clic
      actAs: { Timestampable: ~ }
      columns:
        id:
          type: integer(4)
          fixed: false
          unsigned: true
          primary: true
          autoincrement: true
        dt_debut:
          type: timestamp(25)
          fixed: false
          unsigned: false
          primary: false
          notnull: true
          autoincrement: false
        dt_fin:
          type: timestamp(25)
          fixed: false
          unsigned: false
          primary: false
          notnull: true
          autoincrement: false
        objet_id:
          type: integer(4)
          fixed: false
          unsigned: false
          primary: false
          notnull: true
          autoincrement: false
        enchere_duree_id:
          type: integer(4)
          fixed: false
          unsigned: true
          primary: false
          notnull: true
          autoincrement: false
        enchere_cout_id:
          type: integer(4)
          fixed: false
          unsigned: true
          primary: false
          notnull: true
          autoincrement: false
      relations:
        Objet:
          local: objet_id
          foreign: id
          type: one
        EnchereDuree:
          local: enchere_duree_id
          foreign: id
          type: one
        EnchereCout:
          local: enchere_cout_id
          foreign: id
          type: one
        EnchereClicHisto:
          local: id
          foreign: enchere_clic_id
          type: many
    EnchereClicHisto:
      connection: doctrine
      tableName: enchere_clic_histo
      actAs: { Timestampable: ~ }
      columns:
        id:
          type: integer(4)
          fixed: false
          unsigned: true
          primary: true
          autoincrement: true
        enchere_clic_id:
          type: integer(4)
          fixed: false
          unsigned: true
          primary: false
          notnull: true
          autoincrement: false
        client_id:
          type: integer(4)
          fixed: false
          unsigned: true
          primary: false
          notnull: true
          autoincrement: false
        nb_credit:
          type: integer(4)
          fixed: false
          unsigned: true
          primary: false
          notnull: true
          autoincrement: false
      relations:
        EnchereClic:
          local: enchere_clic_id
          foreign: id
          type: one
        Client:
          local: client_id
          foreign: id
          type: one
    EnchereCout:
      connection: doctrine
      tableName: enchere_cout
      actAs: { Timestampable: ~ }
      columns:
        id:
          type: integer(4)
          fixed: false
          unsigned: true
          primary: true
          autoincrement: true
        cout:
          type: integer(4)
          fixed: false
          unsigned: true
          primary: false
          notnull: true
          autoincrement: false
      relations:
        EnchereClic:
          local: id
          foreign: enchere_cout_id
          type: many
        EnchereExp:
          local: id
          foreign: enchere_cout_id
          type: many
    EnchereDuree:
      connection: doctrine
      tableName: enchere_duree
      actAs: { Timestampable: ~ }
      columns:
        id:
          type: integer(4)
          fixed: false
          unsigned: true
          primary: true
          autoincrement: true
        duree:
          type: integer(4)
          fixed: false
          unsigned: true
          primary: false
          notnull: true
          autoincrement: false
      relations:
        EnchereClic:
          local: id
          foreign: enchere_duree_id
          type: many
    Le problème est donc que je n'arrive pas a récupérer les valeur cout et durée contenu dans les tables correspondantes alors que les liaisons sont faite dans le shema et dans la requête doctrine.

    Si vous avez une idée je suis preneur.

    Merci

    PS : merci pour la technique du code en continu.

  4. #4
    Expert éminent
    Avatar de Michel Rotta
    Homme Profil pro
    DPO
    Inscrit en
    Septembre 2005
    Messages
    4 954
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    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
    Points : 8 486
    Points
    8 486
    Par défaut
    J'essayerais ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    $this->enchereClicHisto->setNbCredit($this->enchere_clic->getEnchereCout()->getCout());
    Pour récupérer une relation getNomDeLaRelation() vu que c'est une méthode.

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 9
    Points : 7
    Points
    7
    Par défaut
    J'avais déjà essayé et je viens de réessayer en vérifiant bien la syntaxe mais sa ne fonctionne pas j'ai toujours une erreur à cette ligne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Fatal error: Call to undefined method Doctrine_Collection::getEnchereCout() in /home/sfproject/bigenchere/apps/frontend/modules/enchereclic/actions/actions.class.php on line 88
    Par contre j'ai remarqué que l'objet est de type "Doctrine_Collection" ne devrais t'il pas contenir qu'un seul élément plutôt qu'une collection d'éléments. Et si je fais un dump de cette collection le résultat est vide pourtant l'id passé en paramètre existe et je ne voit pas ce qui cloche dans ma requête.

    En tout cas merci de votre patience

  6. #6
    Futur Membre du Club
    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 9
    Points : 7
    Points
    7
    Par défaut
    J'ai trouver la solution mais sa me parais vraiment crado

    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
    35
    36
    37
    38
    39
    40
     
    public function executeEncherir(sfWebRequest $request)
      {
    	  //CONTROLE CONNEXION
    	if($this->getUser()->isAuthenticated()!==false){
    		//RECUP INFO CLIENT
    		$this->client = Doctrine::getTable('Client')->find(array($this->getUser()->getAttribute('id')));
    		//CONTROLE CREDIT
    		if($this->client->getCredit()>0){
    			//RECUP INFO ENCHERE
    			$this->enchere_clic = Doctrine::getTable('EnchereClic')->find(array($request->getParameter('id')));
    			//CREATION HISTORIQUE
    			$this->enchereClicHisto=new enchereClicHisto();
    			$this->enchereClicHisto->setClientId($this->getUser()->getAttribute('id'))->setEnchereClicId($request->getParameter('id'))->setNbCredit($this->enchere_clic->getEnchereCout()->getCout())->save();
     
    			//MAJ DT FIN ENCHERE
    			$dtFin=$this->enchere_clic->getDtFin();
    			$dtFin=str_replace('-',':',$dtFin);
    			$dtFin=strtotime($dtFin);
    			$dtFin = date("Y-m-d h:i:s",$dtFin+$this->enchere_clic->getEnchereDuree()->getDuree());
    			$this->enchere_clic->setDtFin($dtFin);
    			$this->enchere_clic->save();
    			//RECUP PRIX
    			$this->enchere_clic_histo = Doctrine_Query::create()
    			  ->select('COUNT(c.id) as prix')
    			  ->from('EnchereClicHisto c')
    			  ->where('c.enchere_clic_id = ?',$request->getParameter('id'))
    			  ->execute();
    			 $this->valid=true;
    		}else{
    		//TODO l'UTILISATEUR N'A PLUS DE CREDIT	
    		$this->valid=false;
    		$this->err='credit';
    		}
    	}else{
    		//TODO L'UTILISATEUR DOIT SE CONNECTEZ OU SINSCRIRE
    		$this->valid=false;
    		$this->err='connect';
    	}
      }

    Donc en passant par Doctrine::getTable on a accès aux méthodes mais en passant par Doctrine_Query::create() c'est un tableau d'objet qui est retourné je récupère donc dans ma vue de cette manière : $enchere_clic_histo[0]->getChamps()

    J'essayerais de refactoriser pour y voir un peu plus clair.

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

    Informations forums :
    Inscription : Avril 2004
    Messages : 396
    Points : 396
    Points
    396
    Par défaut
    Je n'ai pas lu tout le topic, mais il y a un peu de refactoring à faire à mon avis :

    Remplacer ton Doctrine_Query par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
                $this->enchere_clic_histo = Doctrine_Core::getTable('EnchereClicHisto')->createQuery()
                  ->select('COUNT(id) as prix')
                  ->where('enchere_clic_id = ?',$request->getParameter('id'))
                  ->execute();
    Balancer ce code du côté du Model (ici : EnchereClicHistoTable) et se contenter de faire un appel de méthode du côté de ton executeEncherir.

    Créer des méthodes du côté de ton Model (ici : EchereClicHisto) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    function setFinDeCredit()
    {
      $this->valid=false;
      $this->err='credit';
    }
    Pareil pour le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
            $this->valid=false;
            $this->err='connect';
    Et pareil pour updateDateDeFinDEnchere()

    Ton Controler doit contenir le minimum de code. La logique métier doit être du côté du Model.

    Egalement, il vaut mieux éviter des lignes à rallonge comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $this->enchereClicHisto->setClientId($this->getUser()->getAttribute('id'))->setEnchereClicId($request->getParameter('id'))->setNbCredit($this->enchere_clic->getEnchereCout()->getCout())->save();
    C'est horrible pour celui qui passera derrière ton code, ou même toi dans une semaine quand tu voudras modifier quelque chose >__<

    Notamment, tu te sers plusieurs fois de : $request->getParameter('id'). Passe cette valeur dans une variable $user_id ou autre, ça sera plus léger.

    D'ailleurs, tout ce code devrait se retrouver dans une méthode de : EnchereClicHisto.

  8. #8
    Expert éminent
    Avatar de Michel Rotta
    Homme Profil pro
    DPO
    Inscrit en
    Septembre 2005
    Messages
    4 954
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    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
    Points : 8 486
    Points
    8 486
    Par défaut
    J'ai jetté un oeil sur ton modèle, il serait bon de le nettoyer pour mieux le comprendre et le rendre plus viable.

    Supprimer toutes les valeurs par défaut : fixed: false, unsigned: false, primary: false, notnull: false, autoincrement: false...

    Les relations ne doivent être définie que d'un seul côté, sur une seul des deux tables, généralement et plus simplement du côté N de la relation, les éléments à mettre de l'autre côté de la relation sont à mettre en avec le préfix foreign. Pour une relation typique 1-N les paramètres à mettre sont : local, foreign et foreignAlias ; les paramètres par défaut : type et foreignType ne sont pas nécessaire. Le paramètre foreignAlias est le nom vu depuis l'autre table, celle qui est du côté 1 de la relation, le nom va donc pointer sur le côté N et retourner un Doctrine_collection, pour rendre la chose plus lisible, et par convention, on va lui mettre un "s" à la fin.

    La relation entre parents et enfants sera donc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    parent:
      columns:
        nom: string(255)
     
    enfant:
      columns:
        nom: string(255)
        parent_id: integer
      relations:
        parent:
          local: parent_id
          foreign: id
          foreignAlias: enfants
    En fait, on peux même l'écrire plus simplement si les nom "standard" sont utilisés pour les relations
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
      relations:
        parent:
          foreignAlias: enfants
    On vois là tous l'intérêt d'un shema.yml lisible et claire.

    Le schéma ne fait pas que définir la structure de la base de donnée, il définit aussi le fonctionnement du modèle objet de doctrine et il est essentiel qu'il réponde au mieux aux deux problèmes.

    Je te propose de revoir ton schéma et, une fois celui-ci propre tant au niveau de la structure que du modèle, nous pourrons alors arguer autour des DQL.

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

Discussions similaires

  1. Problème à la récupération des objets associés
    Par LinC49 dans le forum Doctrine2
    Réponses: 15
    Dernier message: 10/12/2012, 19h23
  2. problème de récupération de properties dans une action
    Par reneguenon dans le forum Struts 1
    Réponses: 3
    Dernier message: 20/10/2008, 10h40
  3. Réponses: 0
    Dernier message: 27/03/2008, 00h18
  4. [Sécurité] Problème de récupération d'objet sérialisé
    Par Mysticlolly dans le forum Langage
    Réponses: 6
    Dernier message: 31/03/2006, 14h16
  5. [hibernate]Problème de récupération d'objet...
    Par roxx62 dans le forum Hibernate
    Réponses: 1
    Dernier message: 07/07/2005, 11h36

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