【Yii】挂件widget

来源:互联网 发布:c语言课程设计小论文 编辑:程序博客网 时间:2024/06/11 16:25

widget好处是方面重用和灵活移动。CWidget是所有的widge父类,同时它又是是CBaseController的子类,CWidget提供了类似CController中的一些方法,但render()方法渲染的时候不带layout,而且渲染的时候$this指得是CWidget对象,而不是CController对象,CController对象可以通过其中的getController()方法获取,用其子类中需要对init()和run()方法重载以定制不同的挂件。


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

[php] view plaincopy
  1. public function widget($className,$properties=array(),$captureOutput=false)  
  2. {  
  3.     if($captureOutput)  
  4.     {  
  5.         ob_start();  
  6.         ob_implicit_flush(false);  
  7.         $widget=$this->createWidget($className,$properties);  
  8.         $widget->run();  
  9.         return ob_get_clean();  
  10.     }  
  11.     else  
  12.     {  
  13.         $widget=$this->createWidget($className,$properties);  
  14.         $widget->run();    
  15.         return $widget;  
  16.     }  
  17. }  
  18. public function createWidget($className,$properties=array())  
  19. {  
  20.     $widget=Yii::app()->getWidgetFactory()->createWidget($this,$className,$properties);  
  21.     $widget->init();  
  22.     return $widget;  
  23. }  
上面是直接加载挂件方法,通过第三个参数来决定是返回内容还是直接输出内容,widget是通过CWidgetFactory来创建。
以网站常见的面包屑导航为例,下面是视图文件中的代码
[php] view plaincopy
  1. $this->breadcrumbs=array(  
  2. <span style="white-space:pre">  </span>'Users',  
  3. );  
  4. $this->widget('zii.widgets.CBreadcrumbs'array(  
  5. <span style="white-space:pre">  </span>'links'=>$this->breadcrumbs,  
  6. ));   

通过CBaseController的widget()方法,创建CBreadcrumbs挂件,初始化后,执行run()方法渲染内容。

[php] view plaincopy
  1. /** 
  2.  * Renders the content of the portlet. 
  3.  */  
  4. public function run()  
  5. {  
  6.     if(empty($this->links))  
  7.         return;  
  8.   
  9.     echo CHtml::openTag($this->tagName,$this->htmlOptions)."\n";  
  10.     $links=array();  
  11.     if($this->homeLink===null)  
  12.         $links[]=CHtml::link(Yii::t('zii','Home'),Yii::app()->homeUrl);  
  13.     else if($this->homeLink!==false)  
  14.         $links[]=$this->homeLink;  
  15.     foreach($this->links as $label=>$url)  
  16.     {  
  17.         if(is_string($label) || is_array($url))  
  18.             $links[]=CHtml::link($this->encodeLabel ? CHtml::encode($label) : $label$url);  
  19.         else  
  20.             $links[]='<span>'.($this->encodeLabel ? CHtml::encode($url) : $url).'</span>';  
  21.     }  
  22.     echo implode($this->separator,$links);  
  23.     echo CHtml::closeTag($this->tagName);  
  24. }  

另外一个多级布局例子来说明beginWidget()、endWidget()的用法。在脚手架生成的代码中,layout下的column1中的代码
[php] view plaincopy
  1. <?php $this->beginContent('//layouts/main'); ?>  
  2. <div id="content">  
  3.     <?php echo $content; ?>  
  4. </div><!-- content -->  
  5. <?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中
0 0
原创粉丝点击