Recent Comment

I got error when I follow these steps in book

Armed with the knowledge of the benefits of Lazy Loading versus Eager Loading

in Yii, we should make an adjustment to how the Issue model is loaded within the

IssueController::actionView() method. Since we have altered the issues detail

view to display our comments, including the author of the comment, we know it will

be more efficient to use the Eager Loading approach to load our comments along with

their respective authors when we make the call to loadModel() in this method. To do

this, we can add a simple input flag to this loadModel() method to indicate whether

or not we want to load the comments as well.

Alter the IssueController::loadModel() method as shown below:

public function loadModel($withComments=false)

{

if($this->_model===null)

{

if(isset($_GET[‘id’]))

{

if($withComments)

{

$this->_model=Issue::model()->with(array(

‘comments’=>array(‘with’=>‘author’)))

->findbyPk($_GET[‘id’]);

}

else

Iteration 6: Adding User Comments

[ 232 ]

{

$this->_model=Issue::model()->findbyPk($_GET[‘id’]);

}

}

if($this->_model===null)

throw new CHttpException(404,'The requested page does not

exist.’);

}

return $this->_model;

}

Now we can change the call to this method in IssueController::actionView(),

as such:

public function actionView()

{

$issue=$this->loadModel(true);

With this in place, we will load all of our comments, along with their respective

author information, with just one database call.

Creating the widget

Now we are ready to create our new widget to use our new method to display our

recent comments.

As we previously mentioned a widget in Yii is a class that extend from the

framework class CWidget or one of its child classes. We’ll add our new widget to the

protected/components/ directly, as the contents of this folder are already specified

in the main configuration file to be auto-loaded within the application. This way we

won’t have to explicitly import the class every time we wish to use it. We’ll name

our widget RecentComments, so we need to add a php file of the same name to this

directly. Add the following class definition to this newly created RecentComment.

php file:

<?php

/**

  • RecentComments is a Yii widget used to display a list of recent

comments

*/

class RecentComments extends CWidget

{

private $_comments;

public $displayLimit = 5;

public $projectId = null;

public function init()

Chapter 9

[ 233 ]

{

$this->_comments = Comment::model()

->findRecentComments($this->displayLimit,

$this->projectId);

}

public function getRecentComments()

{

return $this->_comments;

}

public function run()

{

// this method is called by CController::endWidget()

$this->render(‘recentComments’);

}

}

The primary work involved when creating a new widget is to override the init()

and run() methods of the base class. The init() method initializes the widget and

is called after its properties have been initialized. The run() method executes the

widget. In this case, we simply initialize the widget by requesting recent comments

based on the $displayLimit and $projectId properties. The execution of the widget

itself simply renders its associated view file, which we have yet to create. view files,

by convention, are placed in views/ directly within the same folder where the widget

resides, and have the same name as the widget, but start with a lowercase letter.

Sticking with convention, create a new file whose fully qualified path is protected/

components/views/renderComments.php. Once created, add the following markup

to that file:

<ul>

<?php foreach($this->getRecentComments() as $comment): ?>

<div class="author">

<?php echo $comment->author->username; ?> added a comment.

</div>

<div class="issue">

<?php echo CHtml::link(CHtml::encode($comment->issue->name),

array(‘issue/view’, ‘id’=>$comment->issue->id)); ?>

</div>

<?php endforeach; ?>

</ul>

This calls the RenderComments widget’s getRecentComments() method, which

returns an array of comments. It then iterates over each of them displaying who

added the comment and the associated issue on which the comment was left.

Iteration 6: Adding User Comments

[ 234 ]

In order to see the results, we need to embed this widget into an existing controller

view file. As previously mentioned, we want to use this widget on the projects listing

page, to display all recent comments across all projects, and also on a specific project

details page, to display the recent comments for just that specific project.

Let’s start with the project listing page. The view file responsible for displaying that

content is protected/views/project/index.php. Open up that file and add the

following at the bottom:

<?php $this->widget(‘RecentComments’); ?>

Now if we view the projects listing page http://localhost/trackstar/index.

php?r=project, we see something similar to the following screenshot:

Please help… can someone tell me what I need to modify to make those codes work… thanks…

here are the errors when I view project

CException

RecentComments cannot find the view "recentComments".

D:\xampp\htdocs\yii\framework\web\widgets\CWidget.php(244)

232 * about how the view script is resolved.

233 * @param array $data data to be extracted into PHP variables and made available to the view script

234 * @param boolean $return whether the rendering result should be returned instead of being displayed to end users

235 * @return string the rendering result. Null if the rendering result is not required.

236 * @throws CException if the view does not exist

237 * @see getViewFile

238 */

239 public function render($view,$data=null,$return=false)

240 {

241 if(($viewFile=$this->getViewFile($view))!==false)

242 return $this->renderFile($viewFile,$data,$return);

243 else

244 throw new CException(Yii::t(‘yii’,’{widget} cannot find the view “{view}”.’,

245 array(’{widget}’=>get_class($this), ‘{view}’=>$view)));

246 }

247 }

Stack Trace

#0

– D:\xampp\htdocs\trackstar\protected\components\RecentComments.php(23): CWidget->render("recentComments")

18 return $this->_comments;

19 }

20 public function run()

21 {

22 // this method is called by CController::endWidget()

23 $this->render(‘recentComments’);

24 }

25 }

#1

  • D:\xampp\htdocs\yii\framework\web\CBaseController.php(166): RecentComments->run()

#2

– D:\xampp\htdocs\trackstar\protected\views\project\index.php(19): CBaseController->widget("RecentComments")

14 <?php $this->widget(‘zii.widgets.CListView’, array(

15 ‘dataProvider’=>$dataProvider,

16 ‘itemView’=>’_view’,

17 )); ?>

18

19 <?php $this->widget(‘RecentComments’); ?>

#3

  • D:\xampp\htdocs\yii\framework\web\CBaseController.php(119): require("D:\xampp\htdocs\trackstar\protected\views\project\index.php")

#4

  • D:\xampp\htdocs\yii\framework\web\CBaseController.php(88): CBaseController->renderInternal("D:\xampp\htdocs\trackstar\protected\views\project\index.php", array("dataProvider" => CActiveDataProvider), true)

#5

  • D:\xampp\htdocs\yii\framework\web\CController.php(866): CBaseController->renderFile("D:\xampp\htdocs\trackstar\protected\views\project\index.php", array("dataProvider" => CActiveDataProvider), true)

#6

  • D:\xampp\htdocs\yii\framework\web\CController.php(779): CController->renderPartial("index", array("dataProvider" => CActiveDataProvider), true)

#7

– D:\xampp\htdocs\trackstar\protected\controllers\ProjectController.php(143): CController->render("index", array("dataProvider" => CActiveDataProvider))

138 public function actionIndex()

139 {

140 $dataProvider=new CActiveDataProvider(‘Project’);

141 $this->render(‘index’,array(

142 ‘dataProvider’=>$dataProvider,

143 ));

144 }

145

146 /**

147 * Manages all models.

148 */

#8

  • D:\xampp\htdocs\yii\framework\web\actions\CInlineAction.php(50): ProjectController->actionIndex()

#9

  • D:\xampp\htdocs\yii\framework\web\CController.php(300): CInlineAction->runWithParams(array("r" => "project"))

#10

  • D:\xampp\htdocs\yii\framework\web\filters\CFilterChain.php(134): CController->runAction(CInlineAction)

#11

  • D:\xampp\htdocs\yii\framework\web\filters\CFilter.php(41): CFilterChain->run()

#12

  • D:\xampp\htdocs\yii\framework\web\CController.php(1144): CFilter->filter(CFilterChain)

#13

  • D:\xampp\htdocs\yii\framework\web\filters\CInlineFilter.php(59): CController->filterAccessControl(CFilterChain)

#14

  • D:\xampp\htdocs\yii\framework\web\filters\CFilterChain.php(131): CInlineFilter->filter(CFilterChain)

#15

  • D:\xampp\htdocs\yii\framework\web\CController.php(283): CFilterChain->run()

#16

  • D:\xampp\htdocs\yii\framework\web\CController.php(257): CController->runActionWithFilters(CInlineAction, array("accessControl"))

#17

  • D:\xampp\htdocs\yii\framework\web\CWebApplication.php(277): CController->run("")

#18

  • D:\xampp\htdocs\yii\framework\web\CWebApplication.php(136): CWebApplication->runController("project")

#19

  • D:\xampp\htdocs\yii\framework\base\CApplication.php(158): CWebApplication->processRequest()

#20

  • D:\xampp\htdocs\trackstar\index.php(13): CApplication->run()

2011-09-29 09:48:21 Apache/2.2.14 (Win32) DAV/2 mod_ssl/2.2.14 OpenSSL/0.9.8l mod_autoindex_color PHP/5.3.1 mod_apreq2-20090110/2.7.1 mod_perl/2.0.4 Perl/v5.10.1 Yii Framework/1.1.8

here are the files my friends…

I’m back again… I got it again… B) here are my files that are working… I am really having a difficulty because I am using 1.1.8, The author of the book should make a thread on every version of yii about code changes that have errors… ;)

It seems pretty, but I still dont get the widget to see the view :P.

The widget cannot find the view and I don’t know why ! :

"RecentComments cannot find the view "recentComments"."

It loads the widget, and in the widget under run() is the issue, where it calls the render(method):

[i][b]

$this->render(‘recentComments’);[/b][/i]

Any help will be appreciated :D

just copy all the codes my friend and make sure you save the recentComments.php not renderComments.php under views folder in components… this will surely work…

Hi Jay-ar,

is your code can run on yii version 1.1.7 ?

Especially for recentComments.php line 5 ?

the code in recentComments.php is like this :

<ul>

<?php foreach($this->getRecentComments() as $comment): ?>

<div class="author">

[b]<?php echo $comment->author->username; ?> added a comment. -------> i have a problem in this line, the author name cannot show and always show error message :

Trying to get property of non-object

C:\xampp\htdocs\testing-yii\ch9\protected\components\views\recentComments.php(5)[/b]

</div>

<div class="issue">

<?php echo CHtml::link(CHtml::encode($comment->issue->name),

array(‘issue/view’, ‘id’=>$comment->issue->id)); ?>

</div>

<?php endforeach; ?>

</ul>

is there any suggestion for my error ? , i also has attached the code in another threat : chapter 9 : Cannot show user author and comments in project list views - page 234 and the link is : http://www.yiiframework.com/forum/index.php?/topic/23784-chapter-9-cannot-show-user-author-and-comments-in-project-list-views-page-234/

Your help will be appreciate.

Thank’s

What you need to do is alter the component class. On the overview page (index.php) of Project, no single projectId is specified (NULL), so the init method does nothing!

if you alter the init method


public function init(){

        if(null !== $this->projectId)

            $this->_comments = Comment::model()->with(array('issue' => array('condition' => 'project_id=' . $this->projectId)))->recent($this->displayLimit)->findAll();

    }

to this it will work:


public function init(){

        if(null !== $this->projectId)

            $this->_comments = Comment::model()->with(array('issue' => array('condition' => 'project_id=' . $this->projectId)))->recent($this->displayLimit)->findAll();

        else

            $this->_comments = Comment::model()->with(array('issue'))->recent($this->displayLimit)->findAll();

    }

Furthermore, the filename of the component class needs to be 4612

RecentCommentsWidget.php
, the Class has the same name. The view file has to be recentCommentsWidget.php.

In your views/project/index.php you can call the widget with


<?php  $this->widget('RecentCommentsWidget'); ?>