在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('');
关键说明
- 关联查询优化:用
joinWith关联查询分组信息,避免循环中多次查询数据库,提升性能。 - 数组结构正确性:Select2要求分组数据为外层是分组名、内层是选项键值对的嵌套数组,组件会自动识别并渲染分组。
- 无分组帖子处理:对
group_id为空的帖子设置默认分组,避免数据遗漏。
内容的提问来源于stack exchange,提问作者Hector
相关产品推荐
相关产品推荐

