Yii 的 CWidget 是可重用的展示層元件,封裝了視圖渲染邏輯與資料處理,支援 `beginWidget`/`endWidget` 成對調用捕獲內容區塊。本文詳細說明 Widget 的建立、配置與視圖渲染完整流程。
protected/
└── widgets/
└── test/
├── TestWidget.php # Widget 類別
└── views/
└── test.php # Widget 視圖檔
<?php
/**
* Test Widget 元件
*/
class TestWidget extends CWidget
{
public $title = '預設標題'; // 可從外部傳入的屬性
public $items = array(); // 資料陣列
/**
* 初始化:beginWidget() 時執行
* 適用:資料查詢、參數驗證、資源註冊
*/
public function init()
{
parent::init();
// 範例:查詢最新文章
if (empty($this->items)) {
$this->items = Post::model()->recent()->limit(5)->findAll();
}
// 註冊 CSS/JS
$this->registerAssets();
}
/**
* 執行渲染:endWidget() 時執行
* 適用:視圖渲染、輸出 HTML
*/
public function run()
{
// 渲染 Widget 視圖,傳遞變數
$this->render('test', array(
'title' => $this->title,
'items' => $this->items,
'widget' => $this, // 傳遞自身引用
));
}
protected function registerAssets()
{
$assets = Yii::app()->assetManager->publish(
dirname(__FILE__) . '/assets'
);
Yii::app()->clientScript->registerCssFile($assets . '/widget.css');
}
}
protected/widgets/test/views/test.php
<div class="widget-test">
<h3><?php echo CHtml::encode($title); ?></h3>
<ul>
<?php foreach ($items as $item): ?>
<li>
<?php echo CHtml::link(CHtml::encode($item->title), $item->url); ?>
<span class="time"><?php echo date('Y-m-d', $item->create_time); ?></span>
</li>
<?php endforeach; ?>
</ul>
</div>
<?php
$this->beginWidget('application.widgets.test.TestWidget', array(
'title' => '最新文章',
'items' => $customItems,
));
?>
<!-- 這裡的內容可在 Widget 中透過 $this->getContent() 獲取 -->
<p>自定義內容區塊...</p>
<?php $this->endWidget(); ?>
<?php
$this->widget('application.widgets.test.TestWidget', array(
'title' => '熱門標籤',
'items' => Tag::model()->popular()->limit(10)->findAll(),
));
?>
// 控制器 Action 中
$this->render('index', array(
'widgetContent' => $this->renderPartial('//widgets/test', array(
'title' => '側邊欄',
), true), // true = 返回字串而非直接輸出
));
class ListWidget extends CWidget
{
public $modelClass = 'Post';
public $criteria = array();
public $viewFile = '_list';
public $htmlOptions = array('class' => 'widget-list');
public function run()
{
$model = CActiveRecord::model($this->modelClass);
$dataProvider = new CActiveDataProvider($model, array(
'criteria' => $this->criteria,
));
$this->render($this->viewFile, array(
'dataProvider' => $dataProvider,
'htmlOptions' => $this->htmlOptions,
));
}
}
<?php $this->widget('application.widgets.ListWidget', array(
'modelClass' => 'Product',
'criteria' => array(
'condition' => 'status=1 AND category_id=:cat',
'params' => array(':cat' => 5),
'order' => 'create_time DESC',
'limit' => 8,
),
'viewFile' => 'product_grid',
)); ?>
Widget 是 Yii 視圖層複用的核心機制,善用它可大幅減少重複代碼,提升開發效率與維護性。