在本節中,我們將實作留言顯示與建立功能。
為了增強使用者互動性,我們希望在使用者完成輸入每個欄位後,立即提示可能的錯誤。這就是所謂的客戶端輸入驗證。我們將展示如何在 Yii 中無縫且極其容易地完成此操作。請注意,這需要 Yii 1.1.1 或更新版本。
我們不在個別頁面上顯示和建立留言,而是使用文章詳細資訊頁面(由 PostController
的 view
動作產生)。在文章內容顯示下方,我們先顯示屬於該文章的留言列表,然後顯示留言建立表單。
為了在文章詳細資訊頁面上顯示留言,我們修改視圖腳本 /wwwroot/blog/protected/views/post/view.php
如下,
...post view here... <div id="comments"> if($model->commentCount>=1): <h3> echo $model->commentCount . 'comment(s)'; </h3> $this->renderPartial('_comments',array( 'post'=>$model, 'comments'=>$model->comments, )); endif; </div>
在上面,我們呼叫 renderPartial()
來呈現名為 _comments
的部分視圖,以顯示屬於目前文章的留言列表。請注意,在視圖中,我們使用表達式 $model->comments
來檢索文章的留言。這是有效的,因為我們已在 Post
類別中宣告了 comments
關係。評估此表達式將觸發隱式 JOIN 資料庫查詢,以取回正確的留言。此功能稱為 延遲關聯查詢。
部分視圖 _comments
並不是很複雜。它主要遍歷每個留言並顯示其詳細資訊。有興趣的讀者可以參考 /wwwroot/yii/demos/blog/protected/views/post/_comments.php
。
為了處理留言建立,我們首先修改 PostController
的 actionView()
方法如下,
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> if(Yii::app()->user->hasFlash('commentSubmitted')): <div class="flash-success"> echo Yii::app()->user->getFlash('commentSubmitted'); </div> else: $this->renderPartial('/comment/_form',array( 'model'=>$comment, )); endif; </div><!-- comments -->
在上面的程式碼中,如果快閃訊息可用,我們會顯示它。如果沒有,我們透過呈現部分視圖 /wwwroot/blog/protected/views/comment/_form.php
來顯示留言輸入表單。
為了改善使用者體驗,我們可以使用基於 Ajax 的表單欄位驗證,以便在使用者填寫表單時,在將整個表單提交到伺服器之前,就能獲得驗證回饋。為了支援留言表單上的基於 Ajax 的驗證,我們需要對留言表單視圖 /wwwroot/blog/protected/views/comment/_form.php
和 newComment()
方法進行一些小的修改。
在 _form.php
檔案中,我們主要需要將 CActiveForm::enableAjaxValidation 設定為 true,當我們建立 CActiveForm 小工具時
<div class="form"> $form=$this->beginWidget('CActiveForm', array( 'id'=>'comment-form', 'enableAjaxValidation'=>true, )); ...... $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;
}
發現錯字或您認為此頁面需要改進?
在 github 上編輯 !
follow up ...
hit submit by mistake ... (how do I edit my comments by the way ?)
so
$url=$this->getController()->createUrl($this->captchaAction); CHtml::image($url,$alt,$this->imageOptions);
are the important lines. The first one creates an action for the current controller which will look like this (default urls with get parameters) : index.php?r=post/captcha
this url will be used to point to the captcha action CCaptchaAction which will actually render the image with the help of the gd library (see renderImage method of the CCaptchaAction class).
But for all this to work you need to have this url point to the right action and this is done in the actions array of the PostController (see Action section in tne Controller page of the guide)
/** * Declares class-based actions. */ public function actions() { return array( // captcha action renders the CAPTCHA image // this is used by the contact page 'captcha'=>array( 'class'=>'CCaptchaAction', 'backColor'=>0xF5F5F5, ), ); }
hope this helps someone who like me was trying to follow the tutorial without looking at the completed demo code.
verifyCode variabein Comment Model
Hi,
Since I spent 15 mn trying to figure out why the application was returning a
Property "Comment.verifyCode" is not defined.
when trying to setup the new Comment form
I thought I'd share that I think there must exist in th emodel a variable for each Validation Rule that has been set up in thi same model. That is for validation rules for fields that ar not a db field.
Example
for this rule to exist without any errors being returned
array('verifyCode', 'captcha', 'on' => 'insert', 'allowEmpty'=>!Yii::app()->user->isGuest)
the following line must be added in the Comment model
public $verifyCode;
Maybe it was explaned somawhere but if this is the case I missed the info :)
hope htat helps someone
Thanks
is a rule that
addComment
addComment is in the post model
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(); }
what 'commentNeedApproval' is doing
It took me a while to figure out what was going on in the line referring to 'commentNeedApproval' so I figured I'd share the answer.
You have to add an app parameter in the config file main.php
return array( ... // application-level parameters that can be accessed // using Yii::app()->params['paramName'] 'params'=>array( ... 'commentNeedApproval'=>true, ),
Works like a charm!
Signup or Login in order to comment.