php的智能树结构


在 formatSelect 方法中:
添加了 $prefixes 参数,用于跟踪上层的前缀状态
使用了 Unicode 字符来绘制树形结构:
├─ 表示中间的节点
└─ 表示最后一个节点
│ 表示垂直连接线
表示空白填充
一级分类保持无前缀
二级及以上分类根据是否是最后一个节点使用不同符号
通过 $prefixes 数组维护每一层的连接线状态

<?php
namespace app\controller;

use think\facade\Db;

class CategoryController extends Controller
{
    public function index()
    {
        $list = Db::name('category')
            ->field('id,pid,title')
            ->order('id', 'asc')
            ->select()
            ->toArray();
        
        $categorys = $this->buildTree($list);
        $categoryList = $this->formatSelect($categorys, 0, 1);
        
        $category_id = input('category_id', 0);
        
        $this->assign([
            'categorys' => $categoryList,
            'category_id' => $category_id
        ]);
        
        return $this->fetch();
    }
    
    private function buildTree($list, $pid = 0)
    {
        $tree = [];
        foreach ($list as $item) {
            if ($item['pid'] == $pid) {
                $children = $this->buildTree($list, $item['id']);
                if ($children) {
                    $item['children'] = $children;
                }
                $tree[] = $item;
            }
        }
        return $tree;
    }
    
    private function formatSelect($tree, $level = 0, $selectableLevel = 1, $prefixes = [])
    {
        $result = [];
        $total = count($tree);
        
        foreach ($tree as $index => $item) {
            $isLast = ($index == $total - 1);
            
            // 计算当前层级的前缀
            if ($level == 0) {
                $prefix = ''; // 一级分类不加前缀
            } else {
                // 使用美观的树形结构符号
                $currentPrefix = $isLast ? '└─ ' : '├─ ';
                $parentPrefix = implode('', $prefixes);
                $prefix = $parentPrefix . $currentPrefix;
                // 为子节点准备新的前缀数组
                $newPrefixes = array_merge($prefixes, [$isLast ? '   ' : '│  ']);
            }
            
            $result[$item['id']] = [
                'title' => $prefix . $item['title'],
                'selectable' => ($level < $selectableLevel - 1) ? false : true
            ];
            
            if (isset($item['children'])) {
                $children = $this->formatSelect(
                    $item['children'], 
                    $level + 1, 
                    $selectableLevel,
                    $level == 0 ? [] : $newPrefixes
                );
                $result = array_merge($result, $children);
            }
        }
        return $result;
    }
}

模版代码:

<select name="category_id" class="form-control">
    <option value="0">请选择分类</option>
    {foreach $categorys $cid=>$item}
    <option value="{$cid}" 
            {if !$item.selectable}disabled{/if}
            {if $category_id == $cid}selected{/if}>
        {$item.title}
    </option>
    {/foreach}
</select>

原文链接:https://blog.yongit.com/note/1573147.html