YII框架分析筆記7:掛件widget

widget好處是方面重用和靈活移動。CWidget是所有的widge父類,同時它又是是CBaseController的子類,CWidget提供了類似CController中的一些方法,但render()方法渲染的時候不帶layout,而且渲染的時候$this指得是CWidget對象,而不是CController對象,CController對象可以通過其中的getController()方法獲取,用其子類中需要對init()和run()方法重載以定製不同的掛件。


CBaseController提供widget()方法以及beginWidget()、endWidget()方法加載掛件。

public function widget($className,$properties=array(),$captureOutput=false)
{
	if($captureOutput)
	{
		ob_start();
		ob_implicit_flush(false);
		$widget=$this->createWidget($className,$properties);
		$widget->run();
		return ob_get_clean();
	}
	else
	{
		$widget=$this->createWidget($className,$properties);
		$widget->run();	
		return $widget;
	}
}
public function createWidget($className,$properties=array())
{
	$widget=Yii::app()->getWidgetFactory()->createWidget($this,$className,$properties);
	$widget->init();
	return $widget;
}
上面是直接加載掛件方法,通過第三個參數來決定是返回內容還是直接輸出內容,widget是通過CWidgetFactory來創建。
以網站常見的麪包屑導航爲例,下面是視圖文件中的代碼
$this->breadcrumbs=array(
	'Users',
);
$this->widget('zii.widgets.CBreadcrumbs', array(
	'links'=>$this->breadcrumbs,
)); 

通過CBaseController的widget()方法,創建CBreadcrumbs掛件,初始化後,執行run()方法渲染內容。

/**
 * Renders the content of the portlet.
 */
public function run()
{
	if(empty($this->links))
		return;

	echo CHtml::openTag($this->tagName,$this->htmlOptions)."\n";
	$links=array();
	if($this->homeLink===null)
		$links[]=CHtml::link(Yii::t('zii','Home'),Yii::app()->homeUrl);
	else if($this->homeLink!==false)
		$links[]=$this->homeLink;
	foreach($this->links as $label=>$url)
	{
		if(is_string($label) || is_array($url))
			$links[]=CHtml::link($this->encodeLabel ? CHtml::encode($label) : $label, $url);
		else
			$links[]='<span>'.($this->encodeLabel ? CHtml::encode($url) : $url).'</span>';
	}
	echo implode($this->separator,$links);
	echo CHtml::closeTag($this->tagName);
}

另外一個多級佈局例子來說明beginWidget()、endWidget()的用法。在腳手架生成的代碼中,layout下的column1中的代碼
<?php $this->beginContent('//layouts/main'); ?>
<div id="content">
	<?php echo $content; ?>
</div><!-- content -->
<?php $this->endContent(); ?>
代碼中beginContent($view=null,$data=array())其實是對beginWidget('CContentDecorator',array('view'=>$view, 'data'=>$data))再次封裝,創建內容裝飾掛件CContentDecorator,把主視圖傳進去,
與widget()的不同點是通過$this->_widgetStack[]=$widget和$widget=array_pop($this->_widgetStack)),應用棧來操作掛件,在兩個方法中間的內容通過php內容輸出緩衝函數捕獲,所有上面代碼的作用是將<div id="content"><?php echo $content; ?></div>以變量($content)的方式傳給main.php中。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章