You are viewing revision #2 of this wiki article.
This version may not be up to date with the latest version.
You may want to view the differences to the latest version or see the changes made in this revision.
In this tutorial, we describe how to implement multiple layouts for action views in an application. As an example, we assume that the pages in our application will use three different layouts:
- one-column layout: contains only the main content area;
- two-column layout: contains a left sidebar displaying portlets, and the main content area;
- three-column layout: contains a left sidebar displaying portlets, the main content area, and the right sidebar displaying some context information.
Designing Layouts ¶
To simplify the CSS design, we use the 960 Grid System.
Because all layouts have the similar header and footer sections, we first develop the main
layout which will serve as the parent of the three layouts. We store all these layout files under the same folder protected/views/layouts
. Below is the code for the main
layout (stored as the file main.php
):
<html>
<head>
<?php echo CHtml::cssFile(Yii::app()->baseUrl.'/css/reset.css'); ?>
<?php echo CHtml::cssFile(Yii::app()->baseUrl.'/css/text.css'); ?>
<?php echo CHtml::cssFile(Yii::app()->baseUrl.'/css/960.css'); ?>
<?php echo CHtml::cssFile(Yii::app()->baseUrl.'/css/main.css'); ?>
</head>
<body>
<div class="container_16">
<div class="grid_16">
<div id="header">
...site logo and other header content...
</div>
</div>
<div class="clear"> </div>
<div class="grid_16">
...main menu...
</div>
<div class="clear"> </div>
<div class="grid_16">
<?php echo $content; ?>
</div>
<div class="clear"> </div>
<div class="grid_16" id="footer">
...footer content...
</div><!-- footer -->
</div><!-- container -->
</body>
</html>
Next, we will develop those column-based layouts.
We start with the simplest one-column layout which is stored as the file column1.php
:
<?php $this->beginContent(); ?>
<?php $this->widget('Breadcrumbs', array('crumbs'=>$this->crumbs)); ?>
<div id="content">
<?php echo $content; ?>
</div>
<?php $this->endContent(); ?>
In this layout, we enclose the view content in a pair of [CController::beginContent] and [CController::endContent] method calls. Because we do not pass any parameter to the [CController::beginContent], it means the default layout (which is main
we just developed) will be applied to this view.
Notice also that we include a BreadCrumbs
widget at the beginning of the view. The widget is a customly developed to display breadcrumbs (navigation path) of the current page. The reference $this
stands for the current controller, and we use its crumbs
property to store the breadcrumbs data.
We now develop the two-column layout which is stored as the file column2.php
.
<?php $this->beginContent(); ?>
<div class="grid_4 alpha">
<div class="sidebar">
<?php foreach($this->portlets as $class=>$properties)
$this->widget($class,$properties); ?>
</div>
</div>
<div class="grid_12 omega">
<?php $this->widget('Breadcrumbs', array('crumbs'=>$this->crumbs)); ?>
<div id="content">
<?php echo $content; ?>
</div>
</div>
<?php $this->endContent(); ?>
Compared with the one-column layout, this layout adds a sidebar
column in which we render a list of portlets. The specification of portlets are stored in the portlets
property of the current controller.
And finally, we create the three-column layout and save it as column3.php
.
<?php $this->beginContent(); ?>
<div class="grid_4 alpha">
<div class="sidebar">
<?php foreach($this->portlets as $class=>$properties)
$this->widget($class,$properties); ?>
</div>
</div>
<div class="grid_9">
<?php $this->widget('Breadcrumbs', array('crumbs'=>$this->crumbs)); ?>
<div id="content">
<?php echo $content; ?>
</div>
</div>
<div class="grid_3 omega">
<div class="sidebar">
<?php foreach($this->portlets2 as $class=>$properties)
$this->widget($class,$properties); ?>
</div>
</div>
<?php $this->endContent(); ?>
Nothing special here. We add yet another extra sidebar column and display a list of portlets whose specification comes from the portlets2
property of the current controller.
Using Layouts ¶
As we know that the layout of a page (generated by calling [CController::render]) is mainly determined by two properties: [CWebApplication::layout] and [CController::layout]. The former sets the global layout that applies to all pages in the application, while the latter can be used to override the former to specify an individual layout for a particular page.
In order to use the above column-based layouts, we need to configure the [CController::layout] property in each action view. We can configure this property in the controller or action class, but a better place would be in the view script since this is related with rendering. For example, if a post list page needs to use three-column layout, we can have the following code for the list
view:
<?php
$this->layout='column3';
?>
...render the post list...
Similarly, we can set layout
to be column1
or column2
based on requirements.
One thing we are missing here is how to specify the breadcrumbs and portlets since they may vary among different views. Because in all these layouts, we are assuming the current controller has crumbs
, portlets
and portlets2
properties, it is natural that we use a base controller class to define these common properties, and then we can derive from this base class each individual concrete controller class. We may store this base class in the file protected/components/BaseController.php
.
abstract class BaseController extends CController
{
public $crumbs=array();
public $portlets=array();
public $portlets2=array();
}
Now, if we want to display in the list
view two portlets: one showing the post categories, the other showing the recent comments, we can modify the list
view as follows:
<?php
$this->layout='column3';
$this->portlets['PostCategoryPortlet']=array();
$this->portlets['RecentCommentPortlet']=array('count'=>5);
?>
...render the post list...
In the above, we also need to configure the breadcrumbs of the view. We will leave this as an exercise for you.
bug
This seems to go into an endless loop unless I change the line
<?php $this->beginContent(); ?>
to
<?php $this->beginContent('/layouts/main'); ?>
Continue study...
Don't know I am right or not.
To create PostCategoryPortlet.php, you may need to study this.
Creating User Menu Portlet
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.