unchanged
Title
pass variables or content block from view file to layout file
ifIf you use yiic to generate webApplication there willexistsbe alayouts dirlayout folder under the protected/views/, and the Controller class under protected/components which will use by defaultusethese layoutsfiles .files.allAll your controllers may extends the Controller base class directly orindirectly . pleaseindirectly. Please look atthis classthat class, you may find thislines :lines: ~~~ [php]/** */** * @var string the default layout for the controller view. Defaults to '//layouts/column1',** meaning using a single column layout. See 'protected/views/layouts/column1.php'.*/ public*/ public $layout = '//layouts/column1';/** */** * @var array context menu items. This property will be assigned to {@link CMenu::items}.*/ public*/ public $menu = array();/** */** * @var array the breadcrumbs of the current page. The value of this property will** be assigned to {@link CBreadcrumbs::links}. Please refer to {@link CBreadcrumbs::links}** for more details on how to specify this property.*/ public*/ public $breadcrumbs = array(); ~~~ these variables will be shared by all its subClasses (may beyouyour whole XXXController of yourproject ) .project). except the $layout variable the other two usually used to pass variables to layoutfiles :files: ~~~ [php] $this->breadcrumbs=array('Albums'=>array('index'), 'Manage','Albums'=>array('index'), 'Manage', ); $this->menu=array(array('label'=>'Listarray('label'=>'List Album','url'=>array('index')),array('label'=>'Createarray('label'=>'Create Album','url'=>array('create')), ); ~~~ifIf you use gii to generate crud functionality you may see such code in the top section of file(admin.php,index.php,create.php,update.php,view....).(admin.php, index.php, create.php, update.php, view....). "$this" represent the currentcontroller ,controller, so "breadcrumbs" and "menu" are the member variables of controller anditit defined in "Controller"class . now lets take look at layout file "column2":class. Now lets take look at layout file "column2": ~~~ [php] <?php $this->beginContent('//layouts/main'); ?> <div class="container"> <div class="span-19"> <div id="content"> <?php echo $content; ?> </div><!-- content --> </div> <div class="span-5 last"> <div id="sidebar"> <?php $this->beginWidget('zii.widgets.CPortlet', array( 'title'=>'Operations', )); $this->widget('zii.widgets.CMenu', array( 'items'=>$this->menu, 'htmlOptions'=>array('class'=>'operations'), )); $this->endWidget(); ?> </div><!-- sidebar --> </div> </div> <?php $this->endContent(); ?> // and layout main.php: .. <?php if(isset($this->breadcrumbs)):?> <?php $this->widget('zii.widgets.CBreadcrumbs', array( 'links'=>$this->breadcrumbs, )); ?><!-- breadcrumbs --><?php<?php endif?> .. ~~~ so you can see the "$this->menu " and "$this->breadcrumbs" are assigned in view files (create.php, index.php, admin.php ....) ; in yii when some route be executed , lets say (default manner) : "user/create" , UserController::actionCreate function will be called , and in the actionCreate function it will render the create.php view file and using some specified layout file . so the execution order will be : create.php(view file) ----> column2.php(layout file)----> main.php(layout file) . all these file can refer to "$this" variable , so you can pass variable by defining some public var in the "Controller" class . and give it some value in view file then fetch it in layouts file . all above method may be the normal way :) ; you may notice the file render order : view-->column2--->main ; these just the view files if look it further : webapp->userModule->..UserController--->actionCreate-->view--->column2...main.php . any point before the layout files can assign variable and fetch if from layout file . these execution points are in the same php thread and in same request scope . so you can use any global variable to pass value to the following point ($_GET, $_POST ,$_REQUEST, $_COOKIE; Yii::app()->params['xx']='value to be passed to following point '). in my opinion , do not use $_GET|$_POST|$_COOKIE to pass value , $_GET may affect url creation (Contorller::createUrl() or CWebApplication::createUrl()) , using $_POST|$_COOKIE are strange so i prefer use $_REQUEST (because they are in same "request" scope ) , you can freely use anther method to do that , such as a singleton Registry class : ~~~ [php] class Registry /*extends ArrayObject*/ { /** * @var Registry */ private static $_instance; protected function __construct(){ //parent::__construt(array(),ArrayObject::...); } protected function __clone(){ parent::__clone(); } /** * @var array * */ private $_store = array(); /** * @static * @return Registry */ public static function instance(){ if(isset(self::$_instance)){ return self::$_instance; }else{ return self::$_instance = new self(); } } /** * @param $key * @param $value */ public function set($key, $value){ $this->_store[$key] = $value; } /** * @param $key * @param null $default * @return null */ public function get($key,$default = null){ if(isset($this->_store[$key])){ return $this->_store[$key]; }else{ return $default; } } /** * @param $key * @return bool */ function isValid($key) { return isset($this->_store[$key]) || array_key_exists($key,$this->_store) ; } } ~~~ i have create a extension which will be used by some lazy people who don't want to define variables in "Controller" root class (include me :) ): ~~~ [php] class ExtraAttribute extends CBehavior{ private $_attributes; public function __get($name){ try{ return parent::__get($name); }catch(CException $e){ if(isset($this->_attributes[$name])){ return $this->_attributes[$name]; }else{ throw $e; } } } public function __set($name,$value){ try{ // echo __METHOD__; parent::_set($name,$value); }catch(CException $e){ $this->_attributes[$name] = $value; // YiiUtil::dumpObject($this); } } public function canSetProperty($name){ //echo __METHOD__; return true; } public function canGetProperty($name){ // echo __METHOD__; if(parent::canGetProperty($name)){ return true; }elseif(isset($this->_attributes[$name])){ return true; }else{ return false; } } } ~~~ ** usage ** in you base controller : ~~~ [php] class Controller extends CController { public function behaviors(){ return array( 'extraAttribute'=>array( 'class'=>'application.components.ExtraAttribute', ) ); } ~~~ then you can pass any unPreDefined variable in you view file or you actionXXX method : ~~~ [php] // actionXXX() or someView file: $this->anyVariableName = "someValue"; // in your layout file : if(isset($this->anyVariableName)){ // do by $this->anyVariableName value here ... } ~~~ above is about how pass variables to layout file , sometimes the content box in layout file will be different for different views , and we don't want to define variable in "Controller" class , the CClipWidget class come to us just need you define some placeholders in you layout file : ~~~ [php] // in your layout file : if(isset($this->clips['someSpecMenu'])){ echo $this->clips['someSpecMenu']; } // and pass clips in some view file or actionXXX method : $this->beginClip('someSpecMenu'); // echo any content block here ; $this->endClip(); ~~~ that's all ! hope help some body ; here are some topic about it: [Yii - On what circumstances should we use clips? ](http://www.yiiframework.com/forum/index.php/topic/31889-yii-on-what-circumstances-should-we-use-clips/ "Yii - On what circumstances should we use clips? ") [Render Cgridview Pager Separately](http://www.yiiframework.com/forum/index.php/topic/36547-render-cgridview-pager-separately/ "Render Cgridview Pager Separately")