model = $model; } /** * 获取递归树 * * @param integer|array|Collection $items 可以传入某个id 查询这个id的下级树,也可以传一个查询列表结果,将获取这个列表的所有的下级 树 * @param \Closure $resultCb 用来处理每一次查询的结果 比如要取出树中的所有 name * @return Collection */ public function getTree($items = 0, \Closure $resultCb = null) { if (!is_array($items) && !$items instanceof Collection) { $items = $this->getQuery()->where('parent_id', $items)->select(); $resultCb && $items = $resultCb($items); } foreach ($items as $key => &$item) { $child = $this->getTree($item->id, $resultCb); if ($child) { $item->children = $child; } } return $items; } /** * 获取递归树(包含自身) * * @param integer $id * @param \Closure $resultCb 用来处理每一次查询的结果 比如要取出树中的所有 name * @return Collection */ public function getChildren($id, \Closure $resultCb = null) { $self = $this->getQuery()->where('id', $id)->select(); if(!$self) { error_stop('未找到数据'); } $items = $this->getQuery()->where('parent_id', $id)->select(); $resultCb && $items = $resultCb($items); foreach ($items as $key => &$item) { $child = $this->getTree($item->id, $resultCb); if ($child) { $item->children = $child; } } $self[0]->children = $items; return $self; } /** * 检测id 是不是自己的下级 * * @param [type] $parent_id * @param [type] $id * @return void */ public function checkParent($parent_id, $id) { if ($parent_id == $id) { error_stop('当前上级不能是自己'); } $childIds = $this->getChildIds($id); if (in_array($parent_id, $childIds)) { error_stop('当前上级不能是自己的下级'); } return true; } /** * 获取当前对象所属级别 * * @param [type] $object * @return void */ public function getLevel($object) { $parentIds = $this->getParentFields($object, 'id'); return count($parentIds); } /** * 缓存递归获取当前对象的上级 指定字段 * * @param \think\Model|int $id * @param boolean $self 是否包含自己 * @return array */ public function getParentFields($item, $field = 'id', $self = true) { if (!$item instanceof \think\Model) { $item = $this->getQuery()->find($item); if (!$item) { return []; } } // 判断缓存 $cacheKey = 'object-' . $this->getTable() . '-' . $item->id . '-' . $field . '-parent-ids'; $objectIds = cache($cacheKey); if (!$objectIds) { $objectIds = array_reverse($this->recursionGetParentFields($item, $field)); if ($self) { $objectIds[] = $item[$field]; // 加上自己 } // 缓存暂时注释,如果需要,可以打开,请注意后台更新角色记得清除缓存 // cache($cacheKey, $objectIds, (600 + mt_rand(0, 300))); // 加入随机秒数,防止一起全部过期 } return $objectIds; } /** * 递归获取所有上级 id */ private function recursionGetParentFields($item, $field = 'id', $ids = []) { if ($item->parent_id) { $parent = $this->getQuery()->find($item->parent_id); if ($parent) { $ids[] = $parent[$field]; return $this->recursionGetParentFields($parent, $field, $ids); } } return $ids; } /** * 缓存递归获取子对象 id * * @param int $id 要查询的 id * @param boolean $self 是否包含自己 * @return array */ public function getChildIds($id, $self = true) { // 判断缓存 $cacheKey = 'object-' . $this->getTable() . '-' . $id . '-child-ids'; $objectIds = cache($cacheKey); if (!$objectIds) { $objectIds = $this->recursionGetChildIds($id, $self); // 缓存暂时注释,如果需要,可以打开,请注意后台更新角色记得清除缓存 // cache($cacheKey, $objectIds, (600 + mt_rand(0, 300))); // 加入随机秒数,防止一起全部过期 } return $objectIds; } /** * 递归获取子分类 id * */ private function recursionGetChildIds($id, $self) { $ids = $self ? [$id] : []; $childrenIds = $this->getQuery()->where(['parent_id' => $id])->column('id'); if ($childrenIds) { foreach ($childrenIds as $v) { $grandsonIds = $this->recursionGetChildIds($v, true); $ids = array_merge($ids, $grandsonIds); } } return $ids; } /** * 获取当前 查询 * * @return think\model|think\db\Query */ private function getQuery() { if ($this->model instanceof \Closure) { return ($this->model)(); } return $this->model; } /** * 获取表 */ private function getTable() { $query = $this->getQuery(); if ($query instanceof \think\Model) { $table_name = $query->getQuery()->getTable(); } else { $table_name = $query->getTable(); } return $table_name; } }