Understanding Yii Layouts and Views
When learning Yii I found it difficult to match the different layout strategies used in the demo applications that are bundled with Yii, specifically Helloworld, Hangman and Blog.
A layout is essentially another view. Layouts are optional as everything can be done in the view. If all your pages share a common look or feel then you may want to refactor the majority of the static (or nearly static) content into the Layout, leaving the view to provide the body of the content that is specific to that page.
If you’ve written a lot of PHP applications then you’ll recognise the following:
<?php
include("header.php");
?>
The page and maybe some more PHP.
<?php
include("footer.php");
?>
If “The page and maybe some more PHP.” is the view then the rest is the layout. Or to put it another way a layout is a decorator for a view.
A nice example of this is the Blog demo. The view contains all the page specific body but the menus and side bars are held in the layout. You could add the layout to each view and not use layouts at all but this would mean repeating a lot of the same code across all the views.
The first thing to understand is the precedence of the layout overrides. As with all these things the closer to the code that’s running the higher the priority.
- Action: With the highest priority, this layout can be set inside the body of the controller action.
class SiteController extends CController { public function actionIndex() { $this->layout = "mylayout"; $this->render('index'); }
- Controller:The layout can be set at the controller level by overriding the layout variable from the base class.
class PostController extends Controller { public $layout='column2';
- Theme: The layout may be taken from the current theme.
- Module: The layout may be taken from the current module.
- Parent Modules: If the current module has no layout, then traverse up its parents until you find one.
- Default: Finally the Yii application defines the default layout [
Yii::app()->layout
] which is meant as a catch all. - None: All these places are searched but if at the end of the day they don’t point to anything then a layout won’t be used.
/helloworld/
is accessed and Yii looks for the configuration file/helloworld/protected/config/main.php
in order to find the first controller to load.- The
main.php
configuration file is not found so Yii then looks for the default controller called Site. It loads/helloworld/protected/controllers/SiteController.php
- The default action for a controller is Index so
actionIndex()
is called which just echos some stuff to the screen.
/hangman/
is accessed and Yii looks for the configuration file/hangman/protected/config/main.php
in order to find the first controller to load.- The defaultController is game, so Yii loads
/hangman/protected/controllers/GameController.php
- The default action has been set to “play” by overriding the
defaultAction
field of theGameController
class. SoactionPlay()
is called first. - At the end of
actionPlay()
the functionrender()
is called with either “guess” as the view or “play". Let’s continue assuming “play” was selected. - Now Yii will render
/protected/views/game/play.php
into a variable. - Next it will look for a layout to place that rendering. Following the priorities from above it will eventually get to the default layout for the application (CWebApplication) which is
layouts/main.php
- Yii will make sure that
layouts/main.php
exists then it will render that layout, setting $content to the result of rendering the view file.
main.php
is the default catch-all layout and column1.php
& column2.php
are intermediate layout files.
/blog/
is accessed and Yii looks for the configuration file/blog/protected/config/main.php
in order to find the first controller to load.- The defaultController is post, so Yii loads
/blog/protected/controllers/PostController.php
PostController.php
sets the class layout to “column2″, so all views will use “column2″ as their layout.- The default action is Index so
actionIndex()
is called next. When it gets to the end it callsrender()
to render the index view. /blog/protected/views/post/index.php
is used to draw the blog posts and the result is returned to the renderer.- The renderer uses the result of the view-render as the $content in the column2 layout.
- The column2 layout has the following form. It means that stuff between
beginContent
andendContent
will be given to/layouts/main
as its $content.<?php $this->beginContent('/layouts/main'); ?> ...stuff... <?php $this->endContent(); ?>
No feedback yet
Form is loading...