You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Yii2页面加载报错Undefined variable $searchModel,需仅点击筛选后创建该变量

解决Yii2中「Undefined variable $searchModel」错误及按需筛选实现

问题根源

加载首页时触发actionIndex,但该方法未向视图传递表单依赖的$searchModel、$genres、$authors变量,导致视图渲染表单时报错。另外你希望仅点击「Filtering」按钮后才执行筛选逻辑,而非初始化阶段就执行,需调整控制器逻辑,将列表展示与筛选逻辑合并到同一action中,这也是Yii2的常规做法。

解决方案:合并Action逻辑,按需执行筛选

修改控制器代码

将actionIndex和actionFilter的逻辑合并,仅在检测到筛选请求时应用过滤条件:

private function actionPagination($query)
{
    $count = $query->count();

    $pagination = new Pagination([
        'defaultPageSize' => 10,
        'totalCount' => $count,
    ]);

    $books = $query
        ->orderBy('id')
        ->offset($pagination->offset)
        ->limit($pagination->limit)
        ->all();

    return [$books, $pagination];
}

public function actionIndex()
{
    $query = Books::find();
    // 初始化表单所需的下拉选项数据
    $genres = Genres::find()->select(['genre_name', 'id'])->orderBy('genre_name')->indexBy('id')->column();
    $authors = Authors::find()->select(['concat(first_name, " ", last_name)', 'id'])->orderBy('id')->column();
    $authors = array_combine(range(1, count($authors)), $authors);
    
    // 初始化搜索模型,用于渲染表单(必须存在,否则表单无法渲染)
    $searchModel = new Books();
    $requestParams = Yii::$app->request->queryParams;

    // 仅在点击筛选按钮(即表单提交后)才执行筛选逻辑
    if ($searchModel->load($requestParams) && Yii::$app->request->getIsGet()) {
        if ($searchModel->year_filter) {
            $query->andWhere(['year' => $searchModel->year_filter]);
        }
        if ($searchModel->genre_filter) {
            $query->andWhere(['genre_id' => $searchModel->genre_filter]);
        }

        if ($searchModel->author_filter) {
            $query->joinWith('links')
                ->andWhere(['links.author_id' => $searchModel->author_filter]);
        }
    }

    // 处理分页
    list($books, $pagination) = $this->actionPagination($query);

    return $this->render('index', [
        'books' => $books,
        'pagination' => $pagination,
        'totalPages' => max(1, ceil($pagination->totalCount / $pagination->pageSize)),
        'authors' => $authors,
        'genres' => $genres,
        'searchModel' => $searchModel,
    ]);
}

修改视图表单代码

将表单action指向index,并调整重置按钮逻辑,点击后清空筛选参数并返回列表页:

<?php $form = ActiveForm::begin([
    'action' => ['index'],
    'method' => 'get',
    'options' => ['id' => 'filter-form']
]); 
?>

<?= $form->field($searchModel, 'year_filter')->textInput(['id' => 'year-filter-input']) ?>

<?= $form->field($searchModel, 'genre_filter')->dropDownList(
    $genres,
    [
        'prompt' => 'All genres',
        'id' => 'genre-filter-select'
    ]
) ?>

<?= $form->field($searchModel, 'author_filter')->dropDownList(
    $authors,
    [
        'prompt' => 'All authors',
        'id' => 'author-filter-select'
    ]
) ?>

<div class="form-group">
    <?= Html::submitButton('Filtering', ['class' => 'btn btn-primary']) ?>
    <?= Html::a('Reset filter', ['index'], [
        'class' => 'btn btn-outline-secondary reset-filter'
    ]) ?>
</div>

<?php ActiveForm::end(); ?>

关键说明

  1. 必须初始化$searchModel:视图中的ActiveForm依赖$searchModel来渲染字段,所以即使未点击筛选按钮,也需要初始化该变量,否则会报变量未定义错误。我们仅控制筛选逻辑的执行时机,而非模型的初始化时机。
  2. 合并Action的优势:避免重复代码,同时保证分页与筛选逻辑兼容(筛选后的结果依然可以正常分页)。
  3. 重置按钮优化:使用Html::a跳转回无参数的index页面,直接清空所有筛选条件,比JS重置更可靠。

内容的提问来源于stack exchange,提问作者Kadaver99

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 03:14:58