Bonsoir,
lors de la formation cakephp, et du chapitre d'abonnement on a la possibilité de suivre un animal.
Lors de cette souscription on entre dans une table de liaison l'id de l'aniaml pet_id et l'id de l'utilisateur le suivant user_id . Mais probleme je recupère la valeur 0 =(

Voici mon code

public function subscribe($pet_id){
        $this->Pet->id = $pet_id;
        if(!$this->Pet->exists()){ //si cet animal n existe pas
            throw new NotFoundException();
        }
        $conditions = array(
                'Subscription.pet_id' => $pet_id,
                'Subscription.user_id'=> $this->Auth->user('id')
        );
        $this->loadModel('Subscription');
        $count = $this->Subscription->find('count', array(
            'conditions'=> $conditions
        ));
        if($count > 0){
            $this->Session->setFlash('Vous êtes déjà abonné à cet animal', 'flash', array('class'=>'error'));
        }else{
            $this->Subscription->save($conditions);
            $this->Session->setFlash('Vous êtes désormais abonné à cet animal', 'flash', array('class'=>'succes'));     
        }
        return $this->redirect($this->referer());
    }

et le liens de souscription :

<p>
                    <?= $this->Html->link('M\'abonner', array('action' => 'subscribe', 'controller'=> 'Pets', $pet['Pet']['id'], array('escape'=> false, 'class'=>'btn btn-primary'))); ?>
                </p>

une idée ?

30 réponses


Bomber
Auteur
Réponse acceptée

J'ai fait ca une première fois ca ne fonctionnait pas, je le refais une seconde fois ca fonctionne:

$data = array(
                    'pet_id' => $pet_id,
                    'user_id'=> $this->Auth->user('id'));
            $this->Subscription->save($data);

le code complet :

    public function subscribe($pet_id){
        $this->Pet->id = $pet_id;
        if(!$this->Pet->exists()){ //si cet animal n existe pas
            throw new NotFoundException();
        }
        $conditions = array(
                'Subscription.pet_id' => $pet_id,
                'Subscription.user_id'=> $this->Auth->user('id')
        );
        $this->loadModel('Subscription');
        $count = $this->Subscription->find('count', array(
            'conditions'=> $conditions
        ));
        if($count > 0)
        {
            $this->Session->setFlash('Vous êtes déjà abonné à cet animal', 'flash', array('class'=>'error'));
        }
        else
        {
            $data = array(
                    'pet_id' => $pet_id,
                    'user_id'=> $this->Auth->user('id'));
            $this->Subscription->save($data);
            $this->Session->setFlash('Vous êtes désormais abonné à cet animal', 'flash', array('class'=>'succes'));     
        }
        return $this->redirect($this->referer());
    }

Bonjour,
qu'est ce qui vaut 0 ?

Bomber
Auteur

la valeur des champs user_id et pet_id dans ma table

Que renvoit ceci ?

else{
debug($conditions);

$this->Subscription->save($conditions);

debug($this->Subscription->validationErrors);

die();

$this->Session->setFlash('Vous êtes désormais abonné à cet animal', 'flash', array('class'=>'succes'));

}
Bomber
Auteur

un tableau avec les valeurs correctes de mes deux champs

array(
    'Subscription.pet_id' => '3',
    'Subscription.user_id' => '2'
)

Sans le Subscription ça donne quoi ?

Bomber
Auteur

Cette erreur là :

Database Error
Error: SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'user_id' in where clause is ambiguous

SQL Query: SELECT COUNT(*) AS count FROM petsy.subscriptions AS Subscription LEFT JOIN petsy.pets AS Pet ON (Subscription.pet_id = Pet.id) LEFT JOIN petsy.users AS User ON (Subscription.user_id = User.id) WHERE pet_id = 3 AND user_id = 2

arf... je voulais test juste le save ça a impacté le select ^^

Le problème ici c'est le format de ta variable lors de l'enregistrement, elle ne correspond pas au format préconisé par CakePHP dans leur documentation, voici donc comment résoudre le problème:

$this->Subscription->save(array('Subscription' => $conditions));
Bomber
Auteur

Ca ne change rien malheureusement =/

Que vois-tu dans la log SQL (le débug sql de cakephp )

Bomber
Auteur

a quel moment ?

Quand tu fais ton save

Bomber
Auteur

Nr Query Error Affected Num. rows Took (ms)
1 SELECT COUNT() AS count FROM petsy.pets AS Pet WHERE Pet.id = 1 1 1 0
2 SELECT COUNT(
) AS count FROM petsy.subscriptions AS Subscription LEFT JOIN petsy.pets AS Pet ON (Subscription.pet_id = Pet.id) LEFT JOIN petsy.users AS User ON (Subscription.user_id = User.id) WHERE Subscription.pet_id = 1 AND Subscription.user_id = 2 1 1 0
3 INSERT INTO petsy.subscriptions (created) VALUES ('2014-12-09 19:50:57')

Bomber
Auteur

Il ne prend pas en compte mon $conditions =/

et avec un array('Subscription' => $conditions) ?

Bomber
Auteur

c'est pareil

$this->Subscription->create(); juste avant le save? pas mieux?

Bomber
Auteur

deja essayé ca ne fonctionne pas non plus

Bomber, est-ce que tu peux faire un dump de ta base de donnée est la mettre à disposition ? Je vais tester en local pour essayer d'identifier le problème (met la sur un hébergeur (Mega par exemple) ou envois via skype InspiratNetwork ou via e-mail contact@inspirat.fr).

Bomber
Auteur

Voila c'est envoyé sur ton adresse mail.
Merci bien

A quoi ressemble le modèle Subscription ?

Bomber
Auteur
<?php 
class Subscription extends AppModel{

    public $belongsTo = array(
                            'User', 
                            'Pet' => array(
                                'counterCache'  => true //compte automatiquement
                                )
                            );
} 

Donc, j'ai essayer, ton problème de 0 viens de ta variable "$conditions", tu précise le modèle pour les deux champs "Subscription.user_id" et "Subscription.pet_id", c'est ce qui cause le problème.
Voilà à quoi ressemble ma fonction et ça fonctionne pour ma part:

// Dans le fichier App/Controller/PetsController.php
public function subscribe($pet_id) {
        $this->Pet->id = $pet_id;
        if(!$this->Pet->exists())
        {
            throw new NotFoundException();
        }
        $conditions = array(
            'pet_id' => $pet_id,
            'user_id' => $this->Auth->user('id')
        );
        $this->loadModel('Subscription');
        $count = $this->Subscription->find('count', array('conditions' => $conditions));
        if($count > 0)
        {
            $this->Session->setFlash("Vous êtes déjà abonné à cet animal.", 'error');
        }
        else
        {
            $this->Subscription->save($conditions);
            $this->Session->write("Auth.Subscription.$pet_id", $pet_id);
            $this->Session->setFlash("Abonnement ajouté avec succès.", 'success');
        }
        return $this->redirect($this->referer());
    }
Bomber
Auteur

Peux tu m'expliquer la ligne :

$this->Session->write("Auth.Subscription.$pet_id", $pet_id);

je ne comprend pas pourquoi on le fait pour pet_id
Stp.

Sinon, au final, je me retrouve encore avec l'erreur que j'avais tout tout au debut :

(default) 1 query took 0 ms
Nr Query Error Affected Num. rows Took (ms)
1 SELECT COUNT(*) AS count FROM petsy.pets AS Pet WHERE Pet.id = 1 1 1 0
Database Error
Error: SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'user_id' in where clause is ambiguous

SQL Query: SELECT COUNT(*) AS count FROM petsy.subscriptions AS Subscription LEFT JOIN petsy.pets AS Pet ON (Subscription.pet_id = Pet.id) LEFT JOIN petsy.users AS User ON (Subscription.user_id = User.id) WHERE pet_id = 1 AND user_id = 2

Test en réécrivant les données à sauvegarder (en utilisant pas la même variable $conditions) ..

Bomber
Auteur

toujours pareil -_-'

Bomber
Auteur

lorsque je remets les lignes (rajoute le 'Subscription. '):

 $conditions = array(
                'Subscription.pet_id' => $pet_id,
                'Subscription.user_id'=> $this->Auth->user('id')
        );

l'erreur d'ambiguïté disparait mais je me retrouve avec les 0 dans ma table... =/

Je regarde demain pour le soucis d'ambiguïté ;) mais ce sera avec le code que je t'ai donné

Utilise 2 variables ..

Une avec Subscription pour le find, l'autre sans pour le save.