Displaying Posts

In our blog application, a post may be displayed among a list of posts or by itself. The former is implemented as the index operation while the latter the view operation. In this section, we customize both operations to fulfill our initial requirements.

1. Customizing view Operation

The view operation is implemented by the actionView() method in PostController. Its display is generated by the view view with the view file /wwwroot/blog/protected/views/post/view.php.

Below is the relevant code implementing the view operation in PostController:

public function actionView()
{
    $post=$this->loadModel();
    $this->render('view',array(
        'model'=>$post,
    ));
}
 
private $_model;
 
public function loadModel()
{
    if($this->_model===null)
    {
        if(isset($_GET['id']))
        {
            if(Yii::app()->user->isGuest)
                $condition='status='.Post::STATUS_PUBLISHED
                    .' OR status='.Post::STATUS_ARCHIVED;
            else
                $condition='';
            $this->_model=Post::model()->findByPk($_GET['id'], $condition);
        }
        if($this->_model===null)
            throw new CHttpException(404,'The requested page does not exist.');
    }
    return $this->_model;
}

Our change mainly lies in the loadModel() method. In this method, we query the Post table according to the id GET parameter. If the post is not found or if it is not published or archived (when the user is a guest), we will throw a 404 HTTP error. Otherwise the post object is returned to actionView() which in turn passes the post object to the view script for further display.

Tip: Yii captures HTTP exceptions (instances of CHttpException) and displays them in either predefined templates or customized error views. The skeleton application generated by yiic already contains a customized error view in /wwwroot/blog/protected/views/site/error.php. We can modify this file if we want to further customize the error display.

The change in the view script is mainly about ajdusting the formatting and styles of the post display. We will not go into details here. Interested readers may refer to /wwwroot/blog/protected/views/post/view.php.

2. Customizing index Operation

Like the view operation, we customize the index operation in two places: the actionIndex() method in PostController and the view file /wwwroot/blog/protected/views/post/index.php. We mainly need to add the support for displaying a list of posts that are associated with a specified tag.

Below is the modified actionIndex() method in PostController:

public function actionIndex()
{
    $criteria=new CDbCriteria(array(
        'condition'=>'status='.Post::STATUS_PUBLISHED,
        'order'=>'update_time DESC',
        'with'=>'commentCount',
    ));
    if(isset($_GET['tag']))
        $criteria->addSearchCondition('tags',$_GET['tag']);
 
    $dataProvider=new CActiveDataProvider('Post', array(
        'pagination'=>array(
            'pageSize'=>5,
        ),
        'criteria'=>$criteria,
    ));
 
    $this->render('index',array(
        'dataProvider'=>$dataProvider,
    ));
}

In the above, we first create a query criteria for retrieving post list. The criteria states that only published posts should be returned and they should be sorted according to their update time in descending order. Because when displaying a post in the list, we want to show how many comments the post has received, in the criteria we also specify to bring back commentCount, which if you remember, is a relation declared in Post::relations().

In case when a user wants to see posts with a specific tag, we would add a search condition to the criteria to look for the specified tag.

Using the query criteria, we create a data provider, which mainly serves for three purposes. First, it does pagination of the data when too many results may be returned. Here we customize the pagination by setting the page size to be 5. Second, it does sorting according to the user request. And finally, it feeds the paginated and sorted data to widgets or view code for presentation.

After we finish with actionIndex(), we modify the index view as follows. Our change is mainly about adding the h1 header when the user specifies to display posts with a tag.

<?php if(!empty($_GET['tag'])): ?>
<h1>Posts Tagged with <i><?php echo CHtml::encode($_GET['tag']); ?></i></h1>
<?php endif; ?>
 
<?php $this->widget('zii.widgets.CListView', array(
    'dataProvider'=>$dataProvider,
    'itemView'=>'_view',
    'template'=>"{items}\n{pager}",
)); ?>

Note that in the above, we use CListView to display the post list. This widget requires a partial view to display the detail of each individual post. Here we specify the partial view to be _view, which means the file /wwwroot/blog/protected/views/post/_view.php. In this view script, we can acccess the post instance being displayed via a local variable named $data.

$Id$

Total 3 comments

#7149 report it
Dan O&#39;Donnell at 2012/02/27 10:17pm
Don't just copy the view.php from the demo

Although they say that the changes in views/Post/view.php have mainly to do with formatting and styles, you can't just copy the view.php over to your install: they reference _comment which you haven't built yet.

For the _comments view, look here...

#632 report it
Incubusaurus at 2010/04/05 08:47am
Parameters

In the Customizing index Operation section, the application parameter postsPerPage is referenced.

For this to work, the following file needs to be created:

/wwwroot/yii/demos/blog/protected/config/params.php

A copy of this file can be found in the blog demo sample code.

The main web application configuration file then needs updating, so that it loads its parameters from params.php:

/wwwroot/yii/demos/blog/protected/config/main.php

Change this:

'params'=>array(
    // this is used in contact page
    'adminEmail'=>'webmaster@example.com',
),

To this:

'params'=>require(dirname(__FILE__).'/params.php'),
#1833 report it
OriginalCopy at 2009/03/18 04:52pm
actionList and pagination

To add pagination to actionList(), you need to set pageSize:

$pages=new CPagination($postCount);
$pages->pageSize = self::PAGE_SIZE;
$pages->applyLimit($criteria);

Leave a comment

Please to leave your comment.