Bonsoir,

Suite au tuto de Grafikart je veux faire un système de commentaire pour le blog.

J'ai créé quelques commentaires en base, j'arrive à les afficher dans les articles correspondant.
J'ai modifier le view de Post pour pouvoir les afficher.

Par contre je sèche un peu sur l'ajout du commentaire..
Des pistes?

18 réponses


ksta
Réponse acceptée

ha ok je comprenai pas ba oui alors ta deux choix :) soit tu le met en hidden dans le formulaire soit tu l'insère dans l'objet data

si ton champ s’appelle posts_id dans a base alors tu fais :

$this->request->data->posts_id = $posts_id;

juste avant le save ;)

dit toi que si un jour je sais pas tu a envie de rajouter la date alors tu récupère la date dans ta fonction comment et tu l'insère dans data avec le même nom que dans ta base exemple :

ton champs s'appelle dateComment alors :

$this->request->data->dateComment = $date; ETC....

;)

Salut,

Pour ajouter les commentaires tu peux simplement mettre un bouton sous ton Article "Ajouter un commentaire" qui t'affiche un div (Formulaire caché) et puis tu ajoutes simplement ça en base de données dans un table commentaire (Id, Id_article, Id_User, date, text)

warkanix
Auteur

Salut

Le problème c'est que j'aimerais quand même faire une vérification avant.

Je ne sais pas comment atteindre ma fonction comment avec l'action du form..

view/posts/view.php

<!-- Affichage des commentaires-->

            <?php foreach($comments as $k => $v): ?>
                     <hr><p><?php echo $v->content; ?></p>
            <?php endforeach ?>

            <!-- Formulaire de création de commentaire -->
            <form action="<?php echo ... ; ?>" method="post">
        <div class="content">
            <?php echo $this->Form->input('pseudo','Pseudo'); ?>
            <?php echo $this->Form->input('mail','Mail'); ?>
            <?php echo $this->Form->input('content','Message'); ?>
            <div class="submit">
                <input type="submit" value="Valider" >
            </div>
        </div>
    </form>

PostsController

function view($id,$slug){
        $this->loadModel('Post');
        $d'post'] = $this->Post->findFirst(array(
            'fields' => 'Post.id,Post.content,Post.created,Post.name,Post.slug,Category.name as catname,Category.slug as catslug',
            'conditions' => array('Post.online' => 1,'Post.id'=>$id,'Post.type'=>'post'),
            'join' => array('categories as Category'=>'Category.id=Post.category_id')
        ));
                // Pour l'affichage des commentaires
                $this->loadModel('Comment');
                $d'comments'] = $this->Comment->find(array(
                    'conditions' => array('posts_id' => $id , 'Post.type'=>'post', 'Post.online' => 1),
                    'fields' => 'Comment.pseudo,Comment.url,Comment.mail,Comment.content,Comment.created',
                    'order' => 'Comment.created',
                    'join' => array('posts as Post'=>'Post.id=Comment.posts_id')
                 ));

        if(empty($d'post'])){
            $this->e404('Page introuvable'); 
        }
        if($slug != $d'post']->slug){
            $this->redirect("posts/view/id:$id/slug:".$d'post']->slug,301);
        }
        $this->set($d);

    }

CommentsController

function comment($id){
        $this->loadModel('Comment'); 

        if($this->request->data){
            if($this->Comment->validates($this->request->data)){
                $this->Comment->save($this->request->data);
                $this->Session->setFlash('Le commentaire a bien été créé'); 
                //$this->redirect('admin/categories/index'); 
            }else{
                $this->Session->setFlash('Merci de corriger vos informations','error'); 
            }

        }elseif($id){
            $this->request->data = $this->Comment->findFirst(array(
                'conditions' => array('id'=>$id)
            ));
        }
        $d'id'] = $id; 
        $this->set($d);    
    }

Salut,

pour envoyer tes données à l'action comment il faut mettre l'url vers cette action :)

voila comment appeler une action particulière :

<?php echo Router::url('posts/comment'); ?>

donc pour ton cas pour ta form il faut faire ceci :

<!-- Affichage des commentaires-->

           <?php foreach($comments as $k => $v): ?>
                    <hr><p><?php echo $v->content; ?></p>
           <?php endforeach ?>

           <!-- Formulaire de création de commentaire -->

           <!-- l'id correspond à ton id de commentaire -->
           <form action="<?php echo Router::url('comments/comment/'.$id); ?>" method="post">
       <div class="content">
           <?php echo $this->Form->input('pseudo','Pseudo'); ?>
           <?php echo $this->Form->input('mail','Mail'); ?>
           <?php echo $this->Form->input('content','Message'); ?>
           <div class="submit">
               <input type="submit" value="Valider" >
           </div>
       </div>
   </form>

récupère l'id du commentaire pour le mettre dans le echo du formulaire ;)

après validation des données et l'enregistrement tu peut par la suite rediriger ton utilisateur vers le post en question ;)

warkanix
Auteur

Salut !
Tout d'abord merci de ta réponse !
J'arrive a insérer un commentaire mais par contre je ne récupère pas l'id de l'article..
Enfin plutôt je le récupère grâce a $post->id , et je le passe dans le Router::url , mais après je ne vois pas comment l'enregistrer..

Salut,

normalement tu l'enregistre à la ligne 6 de ton code avec

$this->Comment->save($this->request->data);

non? :

function comment($id){
    $this->loadModel('Comment');

    if($this->request->data){
        if($this->Comment->validates($this->request->data)){
            $this->Comment->save($this->request->data);
            $this->Session->setFlash('Le commentaire a bien été créé');
            //$this->redirect('admin/categories/index');
        }else{
            $this->Session->setFlash('Merci de corriger vos informations','error');
        }

    }elseif($id){
        $this->request->data = $this->Comment->findFirst(array(
            'conditions' => array('id'=>$id)
        ));
    }
    $d'id'] = $id;
    $this->set($d);   
}

il y à un problème avec ton code car tu à deux fois des conditions qui sont vrai. je m'explique :

if($this->request->data){

si il y à des données dans la requête = oui car tu envoie les données grâce au formulaire

et ta aussi

}elseif($id)

sinon si $id existe = oui car tu la passer pour récupérer l'id du post que concerne le commentaire.

donc en faite lorsque tu soumet ton formulaire tu ne rentre pas dans le premier mais dans le deuxième a cause du sinon si

cette fonction est utiliser pour quoi?

si tu veut enregistrer le commentaire il faut le mettre dans la condition

}elseif($id)

mais le problème c'est que tu l'utilise pour récupérer un commentaire en particulariter c'est ça?

warkanix
Auteur

non l'id est null par défault donc pas vraiment de probleme :

function comment($posts_id,$id = null){
        debug($this->request->data);
        debug($posts_id);

        $this->loadModel('Comment'); 
        if($this->request->data){
            if($this->Comment->validates($this->request->data)){
                $this->Comment->save($this->request->data);                               
                $this->Session->setFlash('Le commentaire a bien été créé'); 
                $this->redirect('posts/index'); 
            }else{
                $this->Session->setFlash('Merci de corriger vos informations','error'); 
            }

        }elseif($id){
            $this->request->data = $this->Comment->findFirst(array(
                'conditions' => array('id'=>$id)
            ));
        }
        $d'id'] = $id; 
        $this->set($d);    
    }

Au moment du debug, posts_id = "26" et this->request->data vaut :

stdClass Object
(
    [pseudo] => NomPseudo
    [mail] => 
    [content] => Message
)

J'aimerais bien donc que ca s'enregistre en meme temps :s

:) oui en effet $id=null dans ton nouveau code :p car elle est différente de celle d'avant ^^

function comment($posts_id,$id = null){

    debug($posts_id);

    $this->loadModel('Comment');
    if($this->request->data){
        if($this->Comment->validates($this->request->data)){
                //debug pour voir si on rentre dans la condition
            debug($this->request->data);
            $this->Comment->save($this->request->data);                              
            $this->Session->setFlash('Le commentaire a bien été créé');
            $this->redirect('posts/index');
        }else{
            $this->Session->setFlash('Merci de corriger vos informations','error');
        }

    }elseif($id){
        $this->request->data = $this->Comment->findFirst(array(
            'conditions' => array('id'=>$id)
        ));
    }
    $d'id'] = $id;
    $this->set($d);   
}

pour que tes donnée s'enregistre il faut quel rentre dans la condition :) donc on va voir si elle rentre dedant :)

warkanix
Auteur

Oui oui il passe bien dedans et les données du formulaire (pseudo,mail et message) s'enregistre bien.
Mais l'id de l'article par contre je ne voit pas ou c'est que je peut le mettre pour l'enregistrer.
En champs hidden dans le form?

warkanix
Auteur

Ah merci c'est ca qu'il me fallait !
C'est ce que j'avais essayé de faire mais comme un boulet j'avais mis:

$this->request->data = array("posts_id"=>$posts_id);

*
Ca pouvais difficilement marché ...

Oui en effet :)

car en faisant :

$this->request->data = array("posts_id"=>$posts_id);

ta variable data qui était comme ça :

stdClass Object
(
    [pseudo] => NomPseudo
    [mail] =>
    [content] => Message
)

devien :

stdClass Object
(
   [0] => array(
                  'posts_id] => 10 //exemple 
                )
)

sa arrive :)

bonne continuation ;)

warkanix
Auteur

Je reviens pour une dernière question :p(déjà)

Lorsqu'il n'y a pas d'erreur dans le forumaire d'ajout de commentaire , ca se passe nikel ca va bien dans ;view/posts/view.php

//posts/view.php
<div class="section_content">
    <?php $title_for_layout = $post->name; ?>
    <article>   
             <div class="article-header">
                <?php // Affiche l'heure formaté
                    setlocale (LC_TIME, 'fr_FR','fra');  
                    $dateFormat = $post->created; 
                    $date = strftime("%A %d %B %Y",strtotime("$dateFormat"));
                    echo $date;
                ?>               
             </div>
             <h1><?php echo $post->name; ?>, <small><a href="<?php echo Router::url('posts/category/slug:'.$post->catslug); ?>"><?php echo $post->catname; ?></a></small></h1>
            <?php echo $post->content; ?>
   </article>
                <!-- Affichage des commentaires-->

            <?php foreach($comments as $k => $v): ?>
                     <hr><p><?php echo $v->content; ?></p>
            <?php endforeach ?>
    <?php require('comment.php'); ?>
</div>
    <?php require('sidebar.php'); ?>

Par contre quand il y a pas une erreur au niveau du formulaire, et ben ca m'affiche que le formulaire, soit que "comment.php" :

<!-- Formulaire de création de commentaire -->

        <form action="<?php echo Router::url("posts/comment/".$post->id."/".$post->slug."/".date('Y-m-d')."/"); ?>" method="post">
        <div class="content">
            <?php echo $this->Form->input('pseudo','Pseudo *'); ?>
            <?php echo $this->Form->input('mail','Mail *'); ?>
            <?php echo $this->Form->input('content','Message *'); ?>
            <div class="submit">
                <input type="submit" value="Valider" >
            </div>
        </div>
    </form>
        <p>* Champs obligatoire</p>

Et revoila la fonction "comment" qui est maintenant dans PostsController :

/* Fonction qui permet à l'utilisateur de créer son commentaire par rapport à un article
* @param $id L'id de l'article
*/
function comment($posts_id,$slug,$created,$id = null){
$this->loadModel('Comment');
if($this->request->data){
if($this->Comment->validates($this->request->data)){
$this->request->data->posts_id = $posts_id;
$this->request->data->created = $created;
$this->Comment->save($this->request->data);
$this->Session->setFlash('Le commentaire a bien été créé');
$this->redirect("posts/view/id:$posts_id/slug:".$slug);
}else{
$this->loadModel('Post');
$this->Session->setFlash('Merci de corriger vos informations','error');
//$this->redirect("posts/view/id:$posts_id/slug:".$slug);
}

}elseif($id){
$this->request->data = $this->Comment->findFirst(array(
'conditions' => array('id'=>$id)
));
}
$d'id'] = $id;
$this->set($d);
}

Salut j'était entrain d'écrir quand tu à modifier ton posts :)

tu à la redirection en commentaire dans ton code :) c'est normale?

le mieux serait de rediriger l'utilisateur sur le post qu'il vient de commenter que se soit valide ou non :) car si tu ne fait pas de redirection tu n'aura pas le post concerner juste la vue correspondante donc personnellement je mettrait un redirection :)

après si tu veut absolument une vue comment alors il faut ecrir le code de la fonction view dans la fonction comment et rajouter le code html qui est dans view dans le fichier comment se qui fait sa :

/* Fonction qui permet à l'utilisateur de créer son commentaire par rapport à un article
* @param $id L'id de l'article
*/
function comment($posts_id,$slug,$created,$id = null){
    $this->loadModel('Comment');
    if($this->request->data){
        if($this->Comment->validates($this->request->data)){
            $this->request->data->posts_id = $posts_id;
            $this->request->data->created = $created;
            $this->Comment->save($this->request->data);
            $this->Session->setFlash('Le commentaire a bien été créé');
            $this->redirect("posts/view/id:$posts_id/slug:".$slug);
        }else{
            $this->loadModel('Post');
            $this->Session->setFlash('Merci de corriger vos informations','error');
            //$this->redirect("posts/view/id:$posts_id/slug:".$slug);

            //code de la fonction view 
            $this->loadModel('Post');
        $d'post'] = $this->Post->findFirst(array(
            'fields' => 'Post.id,Post.content,Post.name,Post.slug,Category.name as catname,Category.slug as catslug',
            'conditions' => array('Post.online' => 1,'Post.id'=>$id,'Post.type'=>'post'),
            'join' => array('categories as Category'=>'Category.id=Post.category_id')
        )); 
            $this->set($d);
        }
    }elseif($id){
        $this->request->data = $this->Comment->findFirst(array(
        'conditions' => array('id'=>$id)
        ));
    }
    $d'id'] = $id;
    $this->set($d);
}

fichier view :

<div class="section_content">
    <?php $title_for_layout = $post->name; ?>
    <article>  
             <div class="article-header">
                <?php // Affiche l'heure formaté
                    setlocale (LC_TIME, 'fr_FR','fra'); 
                    $dateFormat = $post->created;
                    $date = strftime("%A %d %B %Y",strtotime("$dateFormat"));
                    echo $date;
                ?>              
             </div>
             <h1><?php echo $post->name; ?>, <small><a href="<?php echo Router::url('posts/category/slug:'.$post->catslug); ?>"><?php echo $post->catname; ?></a></small></h1>
            <?php echo $post->content; ?>

   </article>
                <!-- Affichage des commentaires-->

            <?php foreach($comments as $k => $v): ?>
                     <hr><p><?php echo $v->content; ?></p>
            <?php endforeach ?>

    <?php require('comment.php'); ?>
</div>
    <?php require('sidebar.php'); ?>
        <!-- Formulaire de création de commentaire -->

    <form action="<?php echo Router::url("posts/comment/".$post->id."/".$post->slug."/".date('Y-m-d')."/"); ?>" method="post">
    <div class="content">
        <?php echo $this->Form->input('pseudo','Pseudo *'); ?>
        <?php echo $this->Form->input('mail','Mail *'); ?>
        <?php echo $this->Form->input('content','Message *'); ?>
        <div class="submit">
            <input type="submit" value="Valider" >
        </div>
    </div>
</form>
    <p>* Champs obligatoire</p>

après c'est mon conseil mais sa évitera les doublons de code inutile car tu ira de toute façon que sa soit valide ou non dans la vue view.php ;)

warkanix
Auteur

je suis d'accord avec toi, je préfère la première solution mais le problème, c'est que si je fais la redirection, je perd les informations de
validation (notifcation + message d'erreur propre a chaque input). ):

C'est ça que je comprend pas ..

heu la je vais pas pouvoir plus te détailler car je par de chez moi mais essaye avec :

$this->request->data = $this->Comment->validates($this->request->data);
$this->redirect("posts/view/id:$posts_id/slug:".$slug);

je sais pas si sa fonctionnera mais si sa marche pas tien moi au jus et demain j'essayerais de voir si tu n'a toujours pas trouver la solution :)

warkanix
Auteur

Ca ne marche toujours pas ):

warkanix
Auteur

Salut,
J'ai trouvé une solution !
Dis moi ce que t'en pense :

//PostsController

/**
    * Affiche un article en particulier
    * Et affiche les commentaires correspondant
    **/
    function view($id,$slug){
        $this->loadModel('Post');
        $d'post'] = $this->Post->findFirst(array(
            'fields' => 'Post.id,Post.content,Post.created,Post.name,Post.slug,Category.name as catname,Category.slug as catslug',
            'conditions' => array('Post.online' => 1,'Post.id'=>$id,'Post.type'=>'post'),
            'join' => array('categories as Category'=>'Category.id=Post.category_id')
        ));
                // Pour l'affichage des commentaires
                $this->loadModel('Comment');
                $d'comments'] = $this->Comment->find(array(
                    'conditions' => array('posts_id' => $id , 'Post.type'=>'post', 'Post.online' => 1),
                    'fields' => 'Comment.pseudo,Comment.url,Comment.mail,Comment.content,Comment.created',
                    'order' => 'Comment.created',
                    'join' => array('posts as Post'=>'Post.id=Comment.posts_id')
                 ));

        if(empty($d'post'])){
            $this->e404('Page introuvable'); 
        }
        if($slug != $d'post']->slug){
            $this->redirect("posts/view/id:$id/slug:".$d'post']->slug,301);
        }
        $this->set($d);
                //CREATION DE COMMENTAIRE
                if($this->request->data){
            if($this->Comment->validates($this->request->data)){
                                $this->request->data->posts_id = $id;
                                $this->request->data->created = date('Y-m-d');
                $this->Comment->save($this->request->data);                               
                $this->Session->setFlash('Le commentaire a bien été créé');

                $this->redirect("posts/view/id:$id/slug:".$slug); 
            }else{
                                $this->loadModel('Post');
                                $this->Session->setFlash('Merci de corriger vos informations','error');
            }
        }

    }

//View de post :

<!-- Affichage des commentaires-->

            <?php foreach($comments as $k => $v): ?>
                     <hr><p><?php echo $v->content; ?></p>
            <?php endforeach ?>
            <!-- Formulaire de création de commentaire -->

        <form action="<?php echo Router::url("posts/view/".$post->id."/".$post->slug); ?>" method="post">
        <div class="content">
            <?php echo $this->Form->input('pseudo','Pseudo *'); ?>
            <?php echo $this->Form->input('mail','Mail *'); ?>
            <?php echo $this->Form->input('content','Message *'); ?>
                        <?php echo $this->Form->input('created','hidden'); ?>
            <div class="submit">
                <input type="submit" value="Valider" >
            </div>
        </div>
    </form>
        <p>* Champs obligatoire</p>

Salut :)

nikel sa t'évite d'avoir une vue supplémentaire et une fonction supplémentaire donc moin de code :)

par contre j'ai vue qu'a la ligne 38 tu avais $this->loadModel('post');

tu peut l'enlever car tu ne l'utilise pas donc sa fera une initialisation de moin ;) et également à la ligne 27 tu à $this->set($d);

je le mettrai à la fin pour une question de logique mais après c'est moi donc à toi de voir ;)

en tous cas bravo :) bon boulot

bonne continuation :)