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

在Yii2 Kartik Select2中实现带分组副标题的选项分组

问题描述

数据库表结构

posts表字段:

'id'
'group_id'
'name'

groups表字段:

'id'
'name'

当前实现代码

目前使用Kartik Select2组件展示posts列表的代码:

$form->field($model, 'post')
    ->widget(
        \kartik\select2\Select2::className(),
        [
            'data' => ArrayHelper::map(Post::find()->all(), 'id', 'name'),
            'options' => [
                'placeholder' => \Yii::t('modules', 'Choose post'),
                'multiple' => true
            ],
            'pluginOptions' => [
                'allowClear' => true,
            ],
        ]
    )->label('');

需求

当前帖子为平铺展示,需要将groups表的name作为分组标题,让posts按对应的group_id分组显示。

尝试的错误代码

尝试以下代码后,出现重复分组名和帖子名:

$result = [];

$posts = ArrayHelper::map(Post::find()->all(), 'id', 'name');
$groups = Group::find()->all();

foreach ($posts as $post) {
    $groups = $groups[$post->group_id] ?? null;
    if (is_null($groups)) {
        $result[$post->id] = $post->name;
    } else {
        $line = [];
        foreach ($groups as $group) {
            $line[$post->group_id . '-' . $group->id] = $group->name;
        }
        $result[$post->name] = $line;
    }
}

正确实现方案

要实现Select2的分组展示,需构建嵌套数组(外层键为分组名称,内层为[post_id => post_name]键值对),同时优化查询避免多次数据库请求。

步骤1:构建正确的分组数据数组

首先确保Post模型已定义与Group的关联(在Post模型中添加public function getGroup() { return $this->hasOne(Group::class, ['id' => 'group_id']); }),然后执行关联查询并构建分组数据:

// 关联查询一次性获取所有帖子及其所属分组
$posts = Post::find()
    ->joinWith('group')
    ->all();

// 构建分组数据
$groupedPosts = [];
foreach ($posts as $post) {
    // 处理无分组的帖子,设置默认分组名
    $groupName = $post->group ? $post->group->name : \Yii::t('modules', 'Uncategorized');
    // 将帖子归入对应分组
    $groupedPosts[$groupName][$post->id] = $post->name;
}

步骤2:修改Select2组件配置

将分组后的数组传入Select2的data参数,可选自定义分组标题样式:

$form->field($model, 'post')
    ->widget(
        \kartik\select2\Select2::className(),
        [
            'data' => $groupedPosts, // 使用分组后的数组
            'options' => [
                'placeholder' => \Yii::t('modules', 'Choose post'),
                'multiple' => true
            ],
            'pluginOptions' => [
                'allowClear' => true,
                // 可选:自定义分组标题的显示样式,让分组更醒目
                'templateResult' => new \yii\web\JsExpression("function(item) {
                    if (item.children) {
                        return '<strong>' + item.text + '</strong>';
                    }
                    return item.text;
                }"),
            ],
        ]
    )->label('');

关键说明

  1. 关联查询优化:用joinWith关联查询分组信息,避免循环中多次查询数据库,提升性能。
  2. 数组结构正确性:Select2要求分组数据为外层是分组名、内层是选项键值对的嵌套数组,组件会自动识别并渲染分组。
  3. 无分组帖子处理:对group_id为空的帖子设置默认分组,避免数据遗漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 11:56:19