3
* CBaseController class file.
5
* @author Qiang Xue <qiang.xue@gmail.com>
6
* @link http://www.yiiframework.com/
7
* @copyright Copyright © 2008-2011 Yii Software LLC
8
* @license http://www.yiiframework.com/license/
13
* CBaseController is the base class for {@link CController} and {@link CWidget}.
15
* It provides the common functionalities shared by controllers who need to render views.
17
* CBaseController also implements the support for the following features:
19
* <li>{@link CClipWidget Clips} : a clip is a piece of captured output that can be inserted elsewhere.</li>
20
* <li>{@link CWidget Widgets} : a widget is a self-contained sub-controller with its own view and model.</li>
21
* <li>{@link COutputCache Fragment cache} : fragment cache selectively caches a portion of the output.</li>
24
* To use a widget in a view, use the following in the view:
26
* $this->widget('path.to.widgetClass',array('property1'=>'value1',...));
30
* $this->beginWidget('path.to.widgetClass',array('property1'=>'value1',...));
31
* // ... display other contents here
35
* To create a clip, use the following:
37
* $this->beginClip('clipID');
38
* // ... display the clip contents
41
* Then, in a different view or place, the captured clip can be inserted as:
43
* echo $this->clips['clipID'];
46
* To use fragment cache, do as follows,
48
* if($this->beginCache('cacheID',array('property1'=>'value1',...))
50
* // ... display the content to be cached here
55
* @author Qiang Xue <qiang.xue@gmail.com>
56
* @version $Id: CBaseController.php 2799 2011-01-01 19:31:13Z qiang.xue $
60
abstract class CBaseController extends CComponent
62
private $_widgetStack=array();
65
* Returns the view script file according to the specified view name.
66
* This method must be implemented by child classes.
67
* @param string $viewName view name
68
* @return string the file path for the named view. False if the view cannot be found.
70
abstract public function getViewFile($viewName);
74
* Renders a view file.
76
* @param string $viewFile view file path
77
* @param array $data data to be extracted and made available to the view
78
* @param boolean $return whether the rendering result should be returned instead of being echoed
79
* @return string the rendering result. Null if the rendering result is not required.
80
* @throws CException if the view file does not exist
82
public function renderFile($viewFile,$data=null,$return=false)
84
$widgetCount=count($this->_widgetStack);
85
if(($renderer=Yii::app()->getViewRenderer())!==null && $renderer->fileExtension==='.'.CFileHelper::getExtension($viewFile))
86
$content=$renderer->renderFile($this,$viewFile,$data,$return);
88
$content=$this->renderInternal($viewFile,$data,$return);
89
if(count($this->_widgetStack)===$widgetCount)
93
$widget=end($this->_widgetStack);
94
throw new CException(Yii::t('yii','{controller} contains improperly nested widget tags in its view "{view}". A {widget} widget does not have an endWidget() call.',
95
array('{controller}'=>get_class($this), '{view}'=>$viewFile, '{widget}'=>get_class($widget))));
100
* Renders a view file.
101
* This method includes the view file as a PHP script
102
* and captures the display result if required.
103
* @param string $_viewFile_ view file
104
* @param array $_data_ data to be extracted and made available to the view file
105
* @param boolean $_return_ whether the rendering result should be returned as a string
106
* @return string the rendering result. Null if the rendering result is not required.
108
public function renderInternal($_viewFile_,$_data_=null,$_return_=false)
110
// we use special variable names here to avoid conflict when extracting data
111
if(is_array($_data_))
112
extract($_data_,EXTR_PREFIX_SAME,'data');
118
ob_implicit_flush(false);
119
require($_viewFile_);
120
return ob_get_clean();
123
require($_viewFile_);
127
* Creates a widget and initializes it.
128
* This method first creates the specified widget instance.
129
* It then configures the widget's properties with the given initial values.
130
* At the end it calls {@link CWidget::init} to initialize the widget.
131
* Starting from version 1.1, if a {@link CWidgetFactory widget factory} is enabled,
132
* this method will use the factory to create the widget, instead.
133
* @param string $className class name (can be in path alias format)
134
* @param array $properties initial property values
135
* @return CWidget the fully initialized widget instance.
137
public function createWidget($className,$properties=array())
139
$widget=Yii::app()->getWidgetFactory()->createWidget($this,$className,$properties);
145
* Creates a widget and executes it.
146
* @param string $className the widget class name or class in dot syntax (e.g. application.widgets.MyWidget)
147
* @param array $properties list of initial property values for the widget (Property Name => Property Value)
148
* @param boolean $captureOutput whether to capture the output of the widget. If true, the method will capture
149
* and return the output generated by the widget. If false, the output will be directly sent for display
150
* and the widget object will be returned. This parameter is available since version 1.1.2.
151
* @return mixed the widget instance when $captureOutput is false, or the widget output when $captureOutput is true.
153
public function widget($className,$properties=array(),$captureOutput=false)
158
ob_implicit_flush(false);
159
$widget=$this->createWidget($className,$properties);
161
return ob_get_clean();
165
$widget=$this->createWidget($className,$properties);
172
* Creates a widget and executes it.
173
* This method is similar to {@link widget()} except that it is expecting
174
* a {@link endWidget()} call to end the execution.
175
* @param string $className the widget class name or class in dot syntax (e.g. application.widgets.MyWidget)
176
* @param array $properties list of initial property values for the widget (Property Name => Property Value)
177
* @return CWidget the widget created to run
180
public function beginWidget($className,$properties=array())
182
$widget=$this->createWidget($className,$properties);
183
$this->_widgetStack[]=$widget;
188
* Ends the execution of the named widget.
189
* This method is used together with {@link beginWidget()}.
190
* @param string $id optional tag identifying the method call for debugging purpose.
191
* @return CWidget the widget just ended running
192
* @throws CException if an extra endWidget call is made
195
public function endWidget($id='')
197
if(($widget=array_pop($this->_widgetStack))!==null)
203
throw new CException(Yii::t('yii','{controller} has an extra endWidget({id}) call in its view.',
204
array('{controller}'=>get_class($this),'{id}'=>$id)));
208
* Begins recording a clip.
209
* This method is a shortcut to beginning {@link CClipWidget}.
210
* @param string $id the clip ID.
211
* @param array $properties initial property values for {@link CClipWidget}.
213
public function beginClip($id,$properties=array())
215
$properties['id']=$id;
216
$this->beginWidget('CClipWidget',$properties);
220
* Ends recording a clip.
221
* This method is an alias to {@link endWidget}.
223
public function endClip()
225
$this->endWidget('CClipWidget');
229
* Begins fragment caching.
230
* This method will display cached content if it is availabe.
231
* If not, it will start caching and would expect a {@link endCache()}
232
* call to end the cache and save the content into cache.
233
* A typical usage of fragment caching is as follows,
235
* if($this->beginCache($id))
237
* // ...generate content here
241
* @param string $id a unique ID identifying the fragment to be cached.
242
* @param array $properties initial property values for {@link COutputCache}.
243
* @return boolean whether we need to generate content for caching. False if cached version is available.
246
public function beginCache($id,$properties=array())
248
$properties['id']=$id;
249
$cache=$this->beginWidget('COutputCache',$properties);
250
if($cache->getIsContentCached())
260
* Ends fragment caching.
261
* This is an alias to {@link endWidget}.
264
public function endCache()
266
$this->endWidget('COutputCache');
270
* Begins the rendering of content that is to be decorated by the specified view.
271
* @param mixed $view the name of the view that will be used to decorate the content. The actual view script
272
* is resolved via {@link getViewFile}. If this parameter is null (default),
273
* the default layout will be used as the decorative view.
274
* Note that if the current controller does not belong to
275
* any module, the default layout refers to the application's {@link CWebApplication::layout default layout};
276
* If the controller belongs to a module, the default layout refers to the module's
277
* {@link CWebModule::layout default layout}.
278
* @param array $data the variables (name=>value) to be extracted and made available in the decorative view.
279
* This parameter has been available since version 1.0.4
281
* @see CContentDecorator
283
public function beginContent($view=null,$data=array())
285
$this->beginWidget('CContentDecorator',array('view'=>$view, 'data'=>$data));
289
* Ends the rendering of content.
292
public function endContent()
294
$this->endWidget('CContentDecorator');