// +---------------------------------------------------------------------- // +---------------------------------------------------------------------- // | 通用的树型类,可以生成任何树型结构 // +---------------------------------------------------------------------- namespace util; class Tree { /** * 生成树型结构所需要的2维数组 * @var array */ public $arr = []; protected static $instance; public $options = []; /** * 生成树型结构所需修饰符号,可以换成图片 * @var array */ public $icon = ['│', '├', '└']; public $nbsp = " "; public $id = "id"; public $pidname = 'parentid'; public $child = 'child'; public $ret = ''; /** * 初始化. * * @param array $options 参数 * * @return Tree */ public static function instance($options = []) { if (is_null(self::$instance)) { self::$instance = new static($options); } return self::$instance; } /** * 构造函数,初始化类 * @param array $arr 2维数组,例如: * array( * 1 => array('id'=>'1','parentid'=>0,'name'=>'一级栏目一'), * 2 => array('id'=>'2','parentid'=>0,'name'=>'一级栏目二'), * 3 => array('id'=>'3','parentid'=>1,'name'=>'二级栏目一'), * 4 => array('id'=>'4','parentid'=>1,'name'=>'二级栏目二'), * 5 => array('id'=>'5','parentid'=>2,'name'=>'二级栏目三'), * 6 => array('id'=>'6','parentid'=>3,'name'=>'三级栏目一'), * 7 => array('id'=>'7','parentid'=>3,'name'=>'三级栏目二') * ) */ public function init($arr = [], $pidname = null, $nbsp = null) { $this->arr = $arr; if (!is_null($pidname)) { $this->pidname = $pidname; } if (!is_null($nbsp)) { $this->nbsp = $nbsp; } $this->ret = ''; return $this; } /** * 得到子级数组 * @param int * @return array */ public function getChild($myid) { $a = $newarr = []; if (is_array($this->arr)) { foreach ($this->arr as $id => $a) { if ($a[$this->pidname] == $myid) { $newarr[$id] = $a; } } } return $newarr; } /** * 读取指定节点的所有孩子节点 * @param int $myid 节点ID * @param boolean $withself 是否包含自身 * @return array */ public function getChildren($myid, $withself = false) { $newarr = []; foreach ($this->arr as $value) { if (!isset($value['id'])) { continue; } if ($value[$this->pidname] == $myid) { $newarr[] = $value; $newarr = array_merge($newarr, $this->getChildren($value['id'])); } elseif ($withself && $value['id'] == $myid) { $newarr[] = $value; } } return $newarr; } /** * 读取指定节点的所有孩子节点ID * @param int $myid 节点ID * @param boolean $withself 是否包含自身 * @return array */ public function getChildrenIds($myid, $withself = false) { $childrenlist = $this->getChildren($myid, $withself); $childrenids = []; foreach ($childrenlist as $k => $v) { $childrenids[] = $v['id']; } return $childrenids; } /** * 得到当前位置父辈数组 * @param int * @return array */ public function getParent($myid) { $pid = 0; $newarr = []; foreach ($this->arr as $value) { if (!isset($value['id'])) { continue; } if ($value['id'] == $myid) { $pid = $value[$this->pidname]; break; } } if ($pid) { foreach ($this->arr as $value) { if ($value['id'] == $pid) { $newarr[] = $value; break; } } } return $newarr; } /** * 得到当前位置所有父辈数组 * @param int * @param bool $withself 是否包含自己 * @return array */ public function getParents($myid, $withself = false) { $pid = 0; $newarr = []; foreach ($this->arr as $value) { if (!isset($value['id'])) { continue; } if ($value['id'] == $myid) { if ($withself) { $newarr[] = $value; } $pid = $value[$this->pidname]; break; } } if ($pid) { $arr = $this->getParents($pid, true); $newarr = array_merge($arr, $newarr); } return $newarr; } /** * 读取指定节点所有父类节点ID * @param int $myid * @param boolean $withself * @return array */ public function getParentsIds($myid, $withself = false) { $parentlist = $this->getParents($myid, $withself); $parentsids = []; foreach ($parentlist as $k => $v) { $parentsids[] = $v['id']; } return $parentsids; } /** * 树型结构Option * @param int $myid 表示获得这个ID下的所有子级 * @param string $itemtpl 条目模板 如:"" * @param mixed $selectedids 被选中的ID,比如在做树型下拉框的时候需要用到 * @param mixed $disabledids 被禁用的ID,比如在做树型下拉框的时候需要用到 * @param string $itemprefix 每一项前缀 * @param string $toptpl 顶级栏目的模板 * @return string */ public function getTree($myid, $itemtpl = '', $selectedids = '', $disabledids = '', $itemprefix = '', $toptpl = '') { if (!$itemtpl) { $itemtpl = ''; } $ret = ''; $number = 1; $childs = $this->getChild($myid); if ($childs) { $total = count($childs); foreach ($childs as $value) { $id = $value['id']; $j = $k = ''; if ($number == $total) { $j .= $this->icon[2]; $k = $itemprefix ? $this->nbsp : ''; } else { $j .= $this->icon[1]; $k = $itemprefix ? $this->icon[0] : ''; } $spacer = $itemprefix ? $itemprefix . $j : ''; if ('' !== $selectedids) { $selected = $selectedids && in_array($id, (is_array($selectedids) ? $selectedids : explode(',', $selectedids))) ? 'selected' : ''; $value = array_merge($value, ['selected' => $selected]); } if ('' !== $disabledids) { $disabled = $disabledids && in_array($id, (is_array($disabledids) ? $disabledids : explode(',', $disabledids))) ? 'disabled' : ''; $value = array_merge($value, ['disabled' => $disabled]); } $value = array_merge($value, ['spacer' => $spacer]); $value = array_combine(array_map(function ($k) { return '@' . $k; }, array_keys($value)), $value); $nstr = strtr((($value["@{$this->pidname}"] == 0 || $this->getChild($id)) && $toptpl ? $toptpl : $itemtpl), $value); $ret .= $nstr; $ret .= $this->getTree($id, $itemtpl, $selectedids, $disabledids, $itemprefix . $k . $this->nbsp, $toptpl); $number++; } } return $ret; } /** * 树型结构UL * @param int $myid 表示获得这个ID下的所有子级 * @param string $itemtpl 条目模板 如:"