Files
hyperf_data/extend/Aether/PHP/Hyperf/Traits/AetherTree.php
Aether 0920cef866 init
2025-09-18 10:46:54 +08:00

126 lines
3.4 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace Aether\Traits;
use Aether\AetherModel;
use Hyperf\Database\Model\Collection;
use LogicException;
trait AetherTree
{
// 初始化时检查当前类是否继承AetherModel
public function __construct(array $attributes = [])
{
parent::__construct($attributes);
if (!$this instanceof AetherModel) {
throw new LogicException(
"使用AetherTree trait的类必须继承AetherModel当前类: " . get_class($this)
);
}
}
/**
* 抽象方法获取父ID字段名由子类实现
*/
abstract protected function getParentIdField(): string;
/**
* 抽象方法:获取排序字段名(由子类实现)
*/
abstract protected function getSortField(): string;
/**
* 构建树形结构
*/
public static function buildTree($items, int $parentId = 0): array
{
$self = new static();
$parentField = $self->getParentIdField();
$sortField = $self->getSortField();
$items = $items instanceof Collection ? $items->toArray() : $items;
$tree = [];
foreach ($items as $item) {
if ($item[$parentField] == $parentId) {
$children = static::buildTree($items, $item['id']);
if (!empty($children)) {
$item['children'] = $children;
}
$tree[] = $item;
}
}
$self->sortTreeItems($tree, $sortField);
return $tree;
}
/**
* 树形节点排序
*/
protected function sortTreeItems(array &$items, string $sortField): void
{
usort($items, function ($a, $b) use ($sortField) {
$direction = $this->treeSortDirection ?? 'asc';
return $direction === 'desc'
? $b[$sortField] <=> $a[$sortField]
: $a[$sortField] <=> $b[$sortField];
});
}
/**
* 获取指定节点的所有子节点ID
*/
public function getChildIds(int $id): array
{
$parentField = $this->getParentIdField();
// 现在可以安全调用newQuery(),因为已通过继承检查
$allItems = $this->newQuery()->get(['id', $parentField])->toArray();
$ids = [$id];
$this->collectChildIds($allItems, $id, $parentField, $ids);
return $ids;
}
/**
* 递归收集子节点ID
*/
private function collectChildIds(array $items, int $parentId, string $parentField, array &$ids): void
{
foreach ($items as $item) {
if ($item[$parentField] == $parentId) {
$ids[] = $item['id'];
$this->collectChildIds($items, $item['id'], $parentField, $ids);
}
}
}
/**
* 获取节点的完整路径
*/
public function getPath(int $id): array
{
$parentField = $this->getParentIdField();
// 安全调用newQuery()
$node = $this->newQuery()->find($id);
if (!$node) {
return [];
}
$path = [$node->toArray()];
$parentId = $node[$parentField];
while ($parentId > 0) {
$parent = $this->newQuery()->find($parentId);
if (!$parent) {
break;
}
array_unshift($path, $parent->toArray());
$parentId = $parent[$parentField];
}
return $path;
}
}