コメントの作成と表示

この節では、コメントの表示と作成の機能を実装します。

ユーザーのインタラクティブ性を向上するために、入力欄への入力が確定するたびにエラー表示をします。いわゆるクライアントサイドの入力検証(client-side input validation)です。これをYiiで行う方法を説明します。シームレスそして極めて簡単にできます。

1. コメントの表示

コメントの表示・作成に個別のページを使う代わりに、記事の詳細ページ(PostControllerviewアクションで生成される)を使います。以下の記事内容の表示では、記事に属するコメント一覧を最初に表示し、それからコメントの投稿フォームを表示します。

記事の詳細ページにコメントを表示するため、ビュースクリプト/wwwroot/blog/protected/views/post/view.phpを以下のように修正します。

...post view here...
 
<div id="comments">
    <?php if($model->commentCount>=1): ?>
        <h3>
            <?php echo $model->commentCount . 'comment(s)'; ?>
        </h3>
 
        <?php $this->renderPartial('_comments',array(
            'post'=>$model,
            'comments'=>$model->comments,
        )); ?>
    <?php endif; ?>
</div>

上の例では、現在の記事に属するコメント一覧を表示するために、_commentsという部分的ビューを指定してrenderPartial()を呼んでいます。ビューでは、$model->commentsという式で、記事のコメントを取得できます。この式が使える理由は、Postクラスでcommentsリレーションを宣言しているからです。この式が評価されると、暗黙的にデータベースのJOINクエリーが発行され、適切なコメントが返されます。この機能はlazy relational queryとして知られています。

部分的ビュー(partial view)の_commentsはあまり興味深いものではありません。コメントを一つ一つ取り扱い、コメントの詳細を表示します。興味のある方は/wwwroot/yii/demos/blog/protected/views/post/_comments.phpを参照してください。

2. コメントの作成

コメントの作成を扱うために、PostControlleractionView()メソッドを以下のように修正します。

public function actionView()
{
    $post=$this->loadModel();
    $comment=$this->newComment($post);
 
    $this->render('view',array(
        'model'=>$post,
        'comment'=>$comment,
    ));
}
 
protected function newComment($post)
{
    $comment=new Comment;
    if(isset($_POST['Comment']))
    {
        $comment->attributes=$_POST['Comment'];
        if($post->addComment($comment))
        {
            if($comment->status==Comment::STATUS_PENDING)
                Yii::app()->user->setFlash('commentSubmitted','Thank you for your comment. Your comment will be posted once it is approved.');
            $this->refresh();
        }
    }
    return $comment;
}

それからPostモデルクラスを修正して、addComment()メソッドを以下のように追加します。

public function addComment($comment)
{
    if(Yii::app()->params['commentNeedApproval'])
        $comment->status=Comment::STATUS_PENDING;
    else
        $comment->status=Comment::STATUS_APPROVED;
    $comment->post_id=$this->id;
    return $comment->save();
}

上記コードでは、viewを表示する前にnewComment()メソッドを呼んでいます。newComment()メソッドでは、Commentインスタンスを生成し、コメントフォームが送信されたかどうかをチェックします。もし送信されていた場合、$post->addComment($comment)を呼んで記事にコメントを追加しようとします。問題なく進んだら記事の詳細ページをリフレッシュします。再表示されたページには、コメント承認制でなければ、新しく投稿されたコメントが表示されます。表示前にコメントの承認が必要な場合は、フラッシュ・メッセージを使って、承認が必要であることをユーザーに示します。フラッシュ・メッセージは大抵、エンドユーザーに確認メッセージを見せるものです。ユーザーがブラウザの再読み込みボタンをクリックしたら、メッセージは消えます。

さらに/wwwroot/blog/protected/views/post/view.phpを修正します。

......
<div id="comments">
    ......
    <h3>Leave a Comment</h3>
 
    <?php if(Yii::app()->user->hasFlash('commentSubmitted')): ?>
        <div class="flash-success">
            <?php echo Yii::app()->user->getFlash('commentSubmitted'); ?>
        </div>
    <?php else: ?>
        <?php $this->renderPartial('/comment/_form',array(
            'model'=>$comment,
        )); ?>
    <?php endif; ?>
 
</div><!-- comments -->

上記コードでは、フラッシュ・メッセージがあれば、そのメッセージを表示します。もし無ければ、部分的ビュー/wwwroot/blog/protected/views/comment/_form.phpを使ってコメント入力フォームを表示します。

3. クライアントサイド・バリデーション

コメントフォームのクライアントサイド・バリデーションをサポートするため、コメントフォームのビュー/wwwroot/blog/protected/views/comment/_form.phpと、newComment()メソッドの両方に小さな変更を加える必要があります。

_form.phpでは、CActiveFormウィジェットを作成するときに、CActiveForm::enableAjaxValidationをtrueに設定します。

<div class="form">
 
<?php $form=$this->beginWidget('CActiveForm', array(
    'id'=>'comment-form',
    'enableAjaxValidation'=>true,
)); ?>
......
<?php $this->endWidget(); ?>
 
</div><!-- form -->

newComment()メソッドでは、AJAXバリデーションのリクエストに応答するためのコードを追加します。このコードはajaxという名前のPOST変数があるかどうかチェックします。もしあれば、CActiveForm::validateを呼んでバリデーション結果を表示します。

protected function newComment($post)
{
    $comment=new Comment;
 
    if(isset($_POST['ajax']) && $_POST['ajax']==='comment-form')
    {
        echo CActiveForm::validate($comment);
        Yii::app()->end();
    }
 
    if(isset($_POST['Comment']))
    {
        $comment->attributes=$_POST['Comment'];
        if($post->addComment($comment))
        {
            if($comment->status==Comment::STATUS_PENDING)
                Yii::app()->user->setFlash('commentSubmitted','Thank you for your comment. Your comment will be posted once it is approved.');
            $this->refresh();
        }
    }
    return $comment;
}
$Id: comment.create.txt 3466 2011-11-28 04:23:54Z jefftulsa $

Be the first person to leave a comment

Please to leave your comment.