項目中會經常遇到需要遞歸的地方,分享一個正在用的一個遞歸查詢。雖然遞歸有時候會慢,但是還沒有找到個好的解決辦法,如果有好的辦法,請分享一下。
<?php
namespace tree;
use app\goods\model\Category;
/**
* 樹結構生成類
*/
class Tree
{
/**
* 根據父級id查詢所有父級id一下的所有分類
* @start
*/
static public $treeList = array(); // 存放無限級分類結果
static public function create($data,$pid = 0){
foreach ($data as $key => $value){
if($value['pid'] == $pid){
self::$treeList[] = $value;
unset($data[$key]);
self::create($data,$value['id']);
}
}
return self::$treeList;
}
/**
* 分類數據處理
* @end
*/
/**
* @var object 對象實例
*/
protected static $instance;
/**
* 配置參數
* @var array
*/
protected static $config = [
'id' => 'id', // id名稱
'pid' => 'pid', // pid名稱
'title' => 'title', // 標題名稱
'child' => 'child', // 子元素鍵名
'html' => '┝ ', // 層級標記
'step' => 4, // 層級步進數量
];
/**
* 架構函數
* @param array $config
*/
public function __construct($config = [])
{
self::$config = array_merge(self::$config, $config);
}
/**
* 配置參數
* @param array $config
* @return object
*/
public static function config($config = [])
{
if (!empty($config)) {
$config = array_merge(self::$config, $config);
}
if (is_null(self::$instance)) {
self::$instance = new static($config);
}
return self::$instance;
}
/**
* 將數據集格式化成層次結構
* @param array/object $lists 要格式化的數據集,可以是數組,也可以是對象
* @param int $pid 父級id
* @param int $max_level 最多返回多少層,0為不限制
* @param int $curr_level 當前層數
* @return array
*/
public static function toLayer($lists = [], $pid = 0, $max_level = 0, $curr_level = 0)
{
$trees = [];
$lists = array_values($lists);
foreach ($lists as $key => $value) {
if ($value[self::$config['pid']] == $pid) {
if ($max_level > 0 && $curr_level == $max_level) {
return $trees;
}
unset($lists[$key]);
$child = self::toLayer($lists, $value[self::$config['id']], $max_level, $curr_level + 1);
if (!empty($child)) {
$value[self::$config['child']] = $child;
}
$trees[] = $value;
}
}
return $trees;
}
/**
* 將數據集格式化成列表結構
* @param array|object $lists 要格式化的數據集,可以是數組,也可以是對象
* @param integer $pid 父級id
* @param integer $level 級別
* @return array 列表結構(一維數組)
*/
public static function toList($lists = [], $pid = 0, $level = 0)
{
if (is_array($lists)) {
$trees = [];
foreach ($lists as $key => $value) {
if ($value[self::$config['pid']] == $pid) {
$title_prefix = str_repeat(" ", $level * self::$config['step']).self::$config['html'];
$value['level'] = $level + 1;
$value['title_prefix'] = $level == 0 ? '' : $title_prefix;
$value['title_display'] = $level == 0 ? $value[self::$config['title']] : $title_prefix.$value[self::$config['title']];
$trees[] = $value;
unset($lists[$key]);
$trees = array_merge($trees, self::toList($lists, $value[self::$config['id']], $level + 1));
}
}
return $trees;
} else {
foreach ($lists as $key => $value) {
if ($value[self::$config['pid']] == $pid && is_object($value)) {
$title_prefix = str_repeat(" ", $level * self::$config['step']).self::$config['html'];
$value['level'] = $level + 1;
$value['title_prefix'] = $level == 0 ? '' : $title_prefix;
$value['title_display'] = $level == 0 ? $value[self::$config['title']] : $title_prefix.$value[self::$config['title']];
$lists->offsetUnset($key);
$lists[] = $value;
self::toList($lists, $value[self::$config['id']], $level + 1);
}
}
return $lists;
}
}
/**
* 根據子節點返回所有父節點
* @param array $lists 數據集
* @param string $id 子節點id
* @return array
*/
public static function getParents($lists = [], $id = '')
{
$trees = [];
foreach ($lists as $value) {
if ($value[self::$config['id']] == $id) {
$trees[] = $value;
$trees = array_merge(self::getParents($lists, $value[self::$config['pid']]), $trees);
}
}
return $trees;
}
/**
* 獲取所有子節點id
* @param array $lists 數據集
* @param string $pid 父級id
* @return array
*/
public static function getChildsId($lists = [], $pid = '')
{
$result = [];
foreach ($lists as $value) {
if ($value[self::$config['pid']] == $pid) {
$result[] = $value[self::$config['id']];
$result = array_merge($result, self::getChildsId($lists, $value[self::$config['id']]));
}
}
return $result;
}
/**
* 獲取所有子節點
* @param array $lists 數據集
* @param string $pid 父級id
* @return array
*/
public static function getChilds($lists = [], $pid = '')
{
$result = [];
foreach ($lists as $value) {
if ($value[self::$config['pid']] == $pid) {
$result[] = $value;
$result = array_merge($result, self::getChilds($lists, $value[self::$config['id']]));
}
}
return $result;
}
/**
* 根據子分類獲取頂級分類
* @param string $id 子分類id
* @return int
*/
public static function getNavPid($id){
$catId = Category::get($id);
if($catId['pid'] != 0){
return self::getNavPid($catId['pid']);
}
return $catId['id'];
}
}