Laravel/PHP实现嵌套数组转特定层级下拉选择框方案
嘿,这个需求我做电商分类系统时经常碰到,用递归就能完美解决!下面给你两种实现方案,纯PHP通用版和Laravel专属的优雅写法,按需取用~
纯PHP 通用实现方案
我们可以写一个递归函数,遍历分类数组,同时传递父级分类的名称作为前缀,这样子分类就能自动带上完整的层级路径:
function buildCategoryOptions(array $categories, string $prefix = ''): string { $options = ''; foreach ($categories as $category) { // 生成当前选项的显示文本,处理前缀和分隔符 $displayText = $prefix ? "{$prefix} >> {$category['name']}" : $category['name']; // 用htmlspecialchars防止XSS攻击,处理特殊字符 $safeText = htmlspecialchars($displayText); $options .= "<option value=\"{$category['id']}\">{$safeText}</option>" . PHP_EOL; // 如果当前分类有子分类,递归处理 if (!empty($category['children'])) { $newPrefix = $prefix ? "{$prefix} >> {$category['name']}" : $category['name']; $options .= buildCategoryOptions($category['children'], $newPrefix); } } return $options; } // 调用函数生成选项 echo buildCategoryOptions($categories);
这个函数会自动遍历所有层级的分类,生成你需要的带路径的<option>标签,而且还做了XSS防护,比较稳妥。
Laravel 专属优雅实现方案
如果是在Laravel项目里,用Blade模板的递归引用会更贴合框架的开发习惯,代码也更易维护:
第一步:创建递归的Blade局部视图
在resources/views/components/category-dropdown.blade.php(路径可以自定义)里写:
@foreach($categories as $category) <option value="{{ $category['id'] }}"> {{ $prefix ?? '' }}{{ $prefix ? ' >> ' : '' }}{{ $category['name'] }} </option> {{-- 如果有子分类,递归加载当前视图 --}} @if(isset($category['children']) && count($category['children']) > 0) @include('components.category-dropdown', [ 'categories' => $category['children'], 'prefix' => ($prefix ?? '') . ($prefix ? ' >> ' : '') . $category['name'] ]) @endif @endforeach
第二步:在主视图中使用
比如在表单里调用这个局部视图:
<select name="category_id" class="form-control"> @include('components.category-dropdown', ['categories' => $categories]) </select>
适配Laravel Eloquent模型(如果用数据库分类)
如果你的分类是存在数据库里的,用Eloquent模型关联的话,只需要稍微调整:
- 首先在
Category模型里定义子分类关联:
namespace App\Models; use Illuminate\Database\Eloquent\Model; class Category extends Model { public function children() { return $this->hasMany(self::class, 'parent_id'); } }
- 控制器里获取顶级分类并预加载子分类:
$categories = Category::whereNull('parent_id')->with('children')->get();
- 最后修改Blade视图里的属性访问方式(从数组下标改成模型属性):
<option value="{{ $category->id }}"> {{ $prefix ?? '' }}{{ $prefix ? ' >> ' : '' }}{{ $category->name }} </option> @if($category->children->isNotEmpty()) @include('components.category-dropdown', [ 'categories' => $category->children, 'prefix' => ($prefix ?? '') . ($prefix ? ' >> ' : '') . $category->name ]) @endif
这样就完全适配Laravel的数据库驱动分类场景了~
内容的提问来源于stack exchange,提问作者Ahmad Badpey
相关产品推荐
相关产品推荐

