Bonjour à tous, je découvre depuis peu CakePHP et je suis confronté à un de mes premiers problèmes. Je voudrais créer un blog où l'on pourrait voir le nombre de commentaires pour chaque article. Mais je coince. Cette fonctionnalité se trouve dans ma fonction admin_index.
Voici ce que j'ai fais pour le moment :

<?php
class PostsController extends AppController{
    public $paginate = array(
            'limit' => 3,
            'order' => array('Post.created ASC'),
            'paramType' => 'querystring',
            'contain' => array('Comment')
        );
    public $hasMany = array('Comment');
    public function beforeFilter(){
        parent::beforeFilter();
        $this->Auth->allow('index', 'view');
    }
    public function index(){
        $posts = $this->paginate('Post');
        $this->set('posts', $posts);
    }
    public function view($slug){
        $post = $this->Post->findBySlug($slug);
        $this->set(compact('post'));

        if(!empty($this->request->data)){
            $this->Post->Comment->create($this->request->data, true);
            $this->request->data'Comment']'post_id'] = $post'Post']'id'];
            if($this->Post->Comment->save(null, true, array('first_name', 'last_name',
                'email', 'content', 'post_id'))){
                $this->Session->setFlash("Votre commentaire à bien été posté","success");
                return $this->redirect($this->referer());
            }else{
                $this->Session->setFlash("Commentaire invalide","alert");
            }
        }
    }

    /* ADMINISTRATION */
     public function admin_index(){
        $posts = $this->Paginate('Post');
        $this->Post->contain('Comment');
            $conditions = array("Post.id = Comment.post_id");
        $this->Post->find('count',  array('conditions' => $conditions));
        debug($conditions);
        $this->set(compact('posts'));
    }
    public function admin_edit($id = null){
        if(!empty($this->request->data)){
            if($this->Post->save($this->request->data)){
                $this->Session->setFlash('Article enregistré', 'success');
                $this->_clean_cache();
                return $this->redirect(array('action' => 'index'));
            }
        }
        elseif($id){
            $this->request->data = $this->Post->findById($id);
        }
    }
    public function admin_delete($id){
        $this->Post->delete($id);
        $this->Session->setFlash('Article supprimé', 'success');
        $this->_clean_cache();
        return $this->redirect($this->referer());
    }
    private function _clean_cache(){
         if(file_exists(CACHE . 'cake_element__sidebar_cache_callbacks')){
            unlink(CACHE . 'cake_element__sidebar_cache_callbacks');
        }
    }
}

L'erreur qui est soulevé, est :
Error: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'contain' at line 1
SQL Query: contain
Notice: If you want to customize this error message, create app\View\Errors\pdo_error.ctp

De plus ayant touché à pas mal de chose il est possible que certains codes ne soit plus très fonctionnel, merci de me prévenir.
Merci à vous.

4 réponses


Pakito
Réponse acceptée

Bonjour,

Tout d'abord, il y a une section CakePhp sur le forum, tu aurais du poster dedans.

Ensuite, quand tu définis ton contain, à moment donné, tu fais ça :

$this->Post->contain('Comment');
            $conditions = array("Post.id = Comment.post_id");
        $this->Post->find('count', array('conditions' => $conditions));

En fait, si tu as bien lié tes modèles entre eux, en définissant le contain, il te remontera uniquement les commentaires relatifs à chaque article.

Pour ton souci de requête, je t'invite à nous mettre éventuellement le debug SQL que ta page t'affiche. En ayant une visibilité sur la requête, on sera en mesure de t'aider.

Pour finir, pour compter les commentaires, pas la peine de partir sur un truc alambiqué :

  • si tu en as besoin partout, tu peux utiliser le counterCache dans tes models
  • si tu n'en as besoin que localement, autant utiliser la fonction count() de PHP sur le tableau qui contient les commentaires de chaque article, et ceci soit dans ton controller, pour l'ajouter aux datas que tu set à la vue, soit directement dans la vue si tu ne l'affiches qu'une fois
Pakito
Réponse acceptée

CounterCache ne prend pas de order, seulement un scope, qui te permet de définir des conditions sur la liaison et le compteur ce liaison.

Pour le order que tu veux pour l'affichage de tes commentaires, c'est soit dans la définition de la relation dans le model, soit dans le contain dans ton controller.

Noudnou
Auteur

Désolé pour le sujet mal placé, je savais pas. La prochaine fois je saurais ;)
Je pense que CounterCache fera l'affaire. J'ai vu sur différents forums qu'il était conseillé pour ce type de besoin. Mais je sais pas trop comment l'utiliser. Est-ce bien cela ?:

var $hasManu = array('Comment' => array(
        'counterCache' => true,
                'order' => 'Comment.created DESC'
    ));

Ma fonction admin_index :

public function admin_index(){
        $posts = $this->Paginate('Post');
        $this->set(compact('posts'));
        debug($posts);
    }

Avec un debug($posts) donne :
\app\Controller\PostsController.php (line 56)
array(
(int) 0 => array(
'Post' => array(
'id' => '1',
'name' => 'Mon tout premier article',
'slug' => 'premier-article',
'content' => 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Saepe, provident, dicta repellat illo et in totam voluptates eaque aliquid ipsum nobis laudantium fuga temporibus animi ipsam tempora accusantium accusamus maiores.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Distinctio, illum asperiores culpa dolor eaque. Maiores reiciendis optio sequi aspernatur autem similique eaque. Velit reprehenderit laboriosam sunt earum consectetur ut fuga!
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Fugiat reiciendis at amet debitis delectus. Ullam, corporis, ea eos quos molestias dicta delectus quibusdam dolor placeat illum debitis commodi esse suscipit!',
'created' => '2014-04-11 16:02:11',
'online' => '1',
'type' => 'post',
'comments' => '0'
),
'Comment' => array(
(int) 0 => array(
'id' => '15',
'first_name' => 'John',
'last_name' => 'Doe',
'email' => 'johndoe.sfr.fr',
'content' => 'Test',
'created' => '2014-04-20 13:55:16',
'post_id' => '1'
)
)
),
(int) 1 => array(
'Post' => array(
'id' => '2',
'name' => 'Deuxième article',
'slug' => 'deuxieme-article',
'content' => 'Ceci n'est pas un contenu.',
'created' => '2014-04-12 09:25:20',
'online' => '1',
'type' => 'post',
'comments' => '0'
),
'Comment' => array()
),
(int) 2 => array(
'Post' => array(
'id' => '3',
'name' => 'Mon troisième article',
'slug' => 'troisieme-article',
'content' => 'Le Lorem Ipsum est simplement du faux texte employé dans la composition et la mise en page avant impression. Le Lorem Ipsum est le faux texte standard de l'imprimerie depuis les années 1500, quand un peintre anonyme assembla ensemble des morceaux de texte pour réaliser un livre spécimen de polices de texte. Il n'a pas fait que survivre cinq siècles, mais s'est aussi adapté à la bureautique informatique, sans que son contenu n'en soit modifié. Il a été popularisé dans les années 1960 grâce à la vente de feuilles Letraset contenant des passages du Lorem Ipsum, et, plus récemment, par son inclusion dans des applications de mise en page de texte, comme Aldus PageMaker.',
'created' => '2014-04-17 20:30:00',
'online' => '1',
'type' => 'posts',
'comments' => '0'
),
'Comment' => array()
)
)

Merci pour votre aide ! :D

Noudnou
Auteur

J'ai pas utilisé le CounterCache, j'ai fais plus simplement :

<?= count($post'Comment']);?>

Ca fonctionne, donc je vais rester là-dessus !
Merci !