Yii2 DropDownList 是表單下拉選單常用元件。本文以「無限分類管理」為例,示範新增時顯示全部分類、編輯時自動排除當前分類 ID (防止選自己當父分類),完整涵蓋控制器資料準備、視圖渲染、ArrayHelper 轉換與提示文字設定。
CREATE TABLE `category` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `pid` INT(11) DEFAULT 0 COMMENT '父分類ID', `title` VARCHAR(100) NOT NULL COMMENT '分類標題', `name` VARCHAR(100) NOT NULL COMMENT '分類別名', `keywords` VARCHAR(255) DEFAULT '', `description` VARCHAR(255) DEFAULT '', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
namespace backend\controllers;
use Yii;
use common\models\Category;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
class CategoryController extends Controller {
public function actionCreate() {
$model = new Category();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
}
return $this->render('form', ['model' => $model]);
}
public function actionUpdate($id) {
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
}
return $this->render('form', ['model' => $model]);
}
protected function findModel($id) {
if (($model = Category::findOne($id)) !== null) return $model;
throw new NotFoundHttpException('頁面不存在');
}
}
<?php
use common\models\Category;
use yii\helpers\ArrayHelper;
use yii\helpers\Html;
use yii\widgets\ActiveForm;
/* @var $this yii\web\View */
/* @var $model common\models\Category */
/* @var $form yii\widgets\ActiveForm */
?>
<div class="category-form">
<?php $form = ActiveForm::begin(); ?>
<?=
$form->field($model, 'title')
->textInput(['maxlength' => 100])
->label('分類標題')
?>
<?=
$form->field($model, 'name')
->textInput(['maxlength' => 100])
->label('分類別名')
?>
<?php
// 關鍵邏輯:編輯時排除自身 ID
if (!$model->isNewRecord) {
$categories = Category::find()
->where(['!=', 'id', $model->id])
->all();
} else {
$categories = Category::find()->all();
}
$cateList = ArrayHelper::map($categories, 'id', 'title');
?>
<?=
$form->field($model, 'pid')
->dropDownList($cateList, [
'prompt' => '請選擇父分類', // 預設提示選項
'class' => 'form-control'
])
->label('父分類')
?>
<?=
$form->field($model, 'keywords')
->textarea(['maxlength' => 255])
->label('分類關鍵詞')
?>
<?=
$form->field($model, 'description')
->textarea(['maxlength' => 255])
->label('分類描述')
?>
<div class="form-group">
<?= Html::submitButton(
$model->isNewRecord ? '建立' : '更新',
['class' => $model->isNewRecord ? 'btn btn-success btn-block' : 'btn btn-primary btn-block']
) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
| 程式碼 | 說明 |
|---|---|
$model->isNewRecord | 判斷是新增還是編輯,決定是否排除自身 |
->where(['!=', 'id', $model->id]) | SQL 條件排除當前分類,避免循環引用 |
ArrayHelper::map($models, 'id', 'title') | 將 ActiveRecord 陣列轉為 [id => title] 鍵值陣列,供 dropDownList 使用 |
'prompt' => '請選擇父分類' | 產生 <option value="">請選擇父分類</option>,value 為空字串 |
'empty' => '無父分類' | 替代寫法,語意相同,prompt 為 Yii2 2.0.11+ 推薦 |
若需在下拉選單顯示層級縮排 (如 `└─ 子分類`),可在查詢後用遞迴函式處理:
function buildTree(array $cats, $pid = 0, $level = 0) {
$result = [];
foreach ($cats as $cat) {
if ($cat['pid'] == $pid) {
$cat['title'] = str_repeat('└─ ', $level) . $cat['title'];
$result[$cat['id']] = $cat['title'];
$result += buildTree($cats, $cat['id'], $level + 1);
}
}
return $result;
}
$allCats = Category::find()->asArray()->all();
$cateList = buildTree($allCats);
$cateList 是否為空陣列、ArrayHelper::map 鍵名是否正確。$model->isNewRecord 判斷正確、where(['!=', 'id', $model->id]) 生效。name 屬性正確、模型 pid 屬性存在、驗證規則允許空值。相關專題:《Yii 框架入門及常用技巧總結》、《PHP 優秀開發框架總結》。