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

Yii2中如何通过Select2将选中值传递至控制器

问题:Kartik Select2多选值无法传递到下载控制器

初始代码(无法获取选中值)

视图代码

<?= $form->field($model, 'msn')->widget(Select2::classname(), [
    'options' => [
        'id' => 'msn-select', // 添加ID属性
        'placeholder' => '选择仪表...',
        'multiple' => true,
    ],
    'pluginOptions' => [
        'allowClear' => true,
        'minimumInputLength' => 1,
        'ajax' => [
            'url' => Url::to(['taskconfig/list']),
            'dataType' => 'json',
            'data' => new JsExpression('function(params) { return {q:params.term}; }'),
            'processResults' => new JsExpression('function(data) { 
            return {
                results: $.map(data.results, function(item) {
                    return {
                        id: item.id,
                        text: item.text
                    };
                })
            };
        }'),
        ],
    ],
])->label('仪表'); ?>
<div class="form-group">
    <?= Html::a('下载Excel', ['download'], ['class' => 'btn btn-primary','id' => 'download-btn']) ?>
</div>

控制器代码

public function actionDownload()
{
    var_dump($_REQUEST);
    die(0);
}

点击「下载Excel」按钮时,控制器返回NULL或array(0) { },无法获取选中的多个值。


更新后的代码

视图代码(改为表单提交)

<div class="task-config-form">
<?php $form = ActiveForm::begin(['id' => 'task','method'=>'post']); ?>

<?= $form->field($model, 'msn')->widget(Select2::classname(), [
    'options' => [
        'id' => 'msn-select', // 添加ID属性
        'placeholder' => '选择仪表...',
        'multiple' => true,
    ],
    'pluginOptions' => [
        'allowClear' => true,
        'minimumInputLength' => 1,
        'ajax' => [
            'url' => Url::to(['taskconfig/list']),
            'dataType' => 'json',
            'data' => new JsExpression('function(params) { return {q:params.term}; }'),
            'processResults' => new JsExpression('function(data) { 
            return {
                results: $.map(data.results, function(item) {
                    return {
                        id: item.id,
                        text: item.text
                    };
                })
            };
        }'),
        ],
    ],
])->label('仪表'); ?>

<div class="form-group">
    <?= Html::submitButton('下载Excel', ['class' => 'btn btn-primary', 'id' => 'download-btn', 'name' => 'download']) ?>
</div>

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

控制器代码

public function actionDownload()
{
    $postData = Yii::$app->request->post();
    $msnArray = $postData['TaskConfig']['msn'];
    // 移除数组中的空值
    $msnArrayFilter = array_filter($msnArray);

    if (empty($msnArrayFilter)) {
        Yii::$app->session->setFlash('error', '未选择任何仪表。');
        return $this->redirect(Yii::$app->request->referrer ?: Yii::$app->homeUrl);
    }

    $dataProvider = new ActiveDataProvider([
        'query' => TaskConfig::find()->select(['msn', 'ak', 'ek', 'utility'])->where(['msn' => $msnArrayFilter]),
        'pagination' => false,
    ]);

    $models = $dataProvider->getModels();

    // 创建Excel文件
    $spreadsheet = new Spreadsheet();
    $sheet = $spreadsheet->getActiveSheet();

    // 设置表头
    $sheet->setCellValue('A1', 'Msn');
    $sheet->setCellValue('B1', 'Ak');
    $sheet->setCellValue('C1', 'Ek');
    $sheet->setCellValue('D1', 'Utility');

    // 填充数据
    $row = 2;
    foreach ($msnArray as $msn)
    {
        // 假设TaskConfig::find()返回的模型包含Excel列对应的属性
        $model = TaskConfig::find()->where(['msn' => $msn])->one();
        if ($model !== null) {
            $sheet->setCellValue('A' . $row, $model->msn);
            $sheet->setCellValue('B' . $row, $model->ak);
            $sheet->setCellValue('C' . $row, $model->ek);
            $sheet->setCellValue('D' . $row, $model->utility);
            $row++;
        }
    }

    // 将Excel文件内容保存到临时文件
    $microseconds = microtime(true); // 获取带微秒的当前时间戳
    $microseconds = str_replace('.', '', $microseconds); // 移除微秒中的点
    $filename = 'task_config_' . date('YmdHis') . '_' . $microseconds . '.xlsx';
    try {
        // 将Excel文件保存到临时位置
        $tempFilePath = sys_get_temp_dir() . '/' . $filename;
        $writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
        $writer->save($tempFilePath);

        // 将文件内容发送给用户下载
        Yii::$app->response->sendFile($tempFilePath, $filename)->send();
        return;
    } catch (\Throwable $e) {
        // 处理异常
        Yii::error('生成Excel文件出错: ' . $e->getMessage());
        Yii::$app->session->setFlash('error', '生成Excel文件时发生错误。');
        return $this->redirect(Yii::$app->request->referrer ?: Yii::$app->homeUrl);
    }
}

问题解决与优化建议

1. 确保多选值正确传递的关键配置

因为是多选场景,表单字段名必须以[]结尾,PHP才能将多个选中值解析为数组。如果ActiveForm没有自动生成正确的名称,可以手动指定:

'options' => [
    'id' => 'msn-select',
    'placeholder' => '选择仪表...',
    'multiple' => true,
    'name' => 'TaskConfig[msn][]' // 手动指定数组格式的字段名
],

2. 控制器取值的安全优化

直接访问$postData['TaskConfig']['msn']存在数组键不存在的风险,建议用更安全的写法:

$taskConfigData = Yii::$app->request->post('TaskConfig', []);
$msnArray = $taskConfigData['msn'] ?? [];

3. 数据查询优化

原代码在foreach循环里逐个查询模型,会产生N+1查询问题,性能低下。可以直接用已获取的$models数组填充Excel:

// 填充数据(优化后)
$row = 2;
foreach ($models as $model)
{
    $sheet->setCellValue('A' . $row, $model->msn);
    $sheet->setCellValue('B' . $row, $model->ak);
    $sheet->setCellValue('C' . $row, $model->ek);
    $sheet->setCellValue('D' . $row, $model->utility);
    $row++;
}

4. 临时文件清理(可选)

生成的临时文件不会自动删除,可在发送文件后添加清理逻辑:

// 发送文件后删除临时文件
register_shutdown_function(function() use ($tempFilePath) {
    if (file_exists($tempFilePath)) {
        unlink($tempFilePath);
    }
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 14:01:04