GridView 批次刪除是後台管理常見需求。核心步驟:(1) GridView 設定 id 與 CheckboxColumn,(2) 頁面放置批次刪除按鈕,(3) JavaScript 取得勾選的主鍵陣列,(4) AJAX 送至後端處理,(5) 完成後 PJAX 重新載入列表。本文提供最精簡可用的完整程式碼。
'grid-pjax']);
echo GridView::widget([
'id' => 'grid', // 關鍵:JS 取得選取列需用此 id
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\CheckboxColumn', 'name' => 'id'], // name 對應主鍵欄位
'id',
'title',
['attribute' => 'status', 'filter' => [0 => '停用', 1 => '啟用']],
['class' => 'yii\grid\ActionColumn'],
],
]);
// 批次刪除按鈕
echo Html::button('批次刪除', ['class' => 'btn btn-danger btn-batch-delete', 'id' => 'btn-batch-delete']);
Pjax::end();
// 註冊 JS
$this->registerJs(<<
response->format = \yii\web\Response::FORMAT_JSON;
$ids = \Yii::$app->request->post('ids', []);
if (!is_array($ids) || !$ids) {
return ['success' => false, 'message' => '無效的 ID 列表'];
}
// 建議:使用交易確保原子性
$transaction = \Yii::$app->db->beginTransaction();
try {
$deleted = Article::deleteAll(['id' => $ids]);
$transaction->commit();
return ['success' => true, 'deleted' => $deleted];
} catch (\Exception $e) {
$transaction->rollBack();
\Yii::error($e->getMessage());
return ['success' => false, 'message' => '伺服器錯誤'];
}
}
?>
若使用 yii\behaviors\SoftDeleteBehavior 或自訂 is_delete 欄位:
is_delete = 1;
return $this->save(false, ['is_delete', 'updated_at']);
}
// Controller
Article::updateAll(['is_delete' => 1, 'updated_at' => time()], ['id' => $ids]);
?>
| 問題 | 原因 | 解決 |
|---|---|---|
| getSelectedRows() 回傳空陣列 | GridView id 未設定或與 JS 選取器不符 | GridView 設定 'id' => 'grid',JS 用 $('#grid') |
| PJAX 重整後按鈕事件失效 | JS 事件綁定在舊 DOM | 使用事件代理 $(document).on('click', '#btn-batch-delete', ...) 或放在 PJAX 容器內重新註冊 |
| CSRF 驗證失敗 | AJAX 未攜帶 CSRF token | Yii2 預設 $.post 會自動帶入 _csrf,確認 meta tag 存在 |
| 刪除大量資料超時 | 單次交易過大 | 分批處理、或使用隊列異步刪除 |