369 lines
9.7 KiB
PHP
369 lines
9.7 KiB
PHP
<?php
|
|
/**
|
|
* Created by PhpStorm.
|
|
* Author:
|
|
* Date: 16/03/2017
|
|
* Time: 08:58
|
|
*/
|
|
|
|
namespace app\common\traits;
|
|
|
|
|
|
use app\common\services\member\MemberRelation;
|
|
use ArrayAccess;
|
|
use BadMethodCallException;
|
|
use Illuminate\Support\Collection;
|
|
use InvalidArgumentException;
|
|
|
|
/**
|
|
* Class TreeTrait
|
|
*
|
|
* 使用
|
|
* <?php
|
|
* namespace app\common\models;
|
|
* use app\common\traits\TreeTrait;
|
|
*
|
|
* class MyClass
|
|
* {
|
|
* use TreeTrait;
|
|
*
|
|
* // 自定义属性(可选)
|
|
* protected $treeNodeIdName = 'id';
|
|
* protected $treeNodeParentIdName = 'parent_id';
|
|
* /**
|
|
* * 获取待处理的原始节点数据
|
|
* *
|
|
* * 必须实现
|
|
* *
|
|
* * return \Illuminate\Support\Collection
|
|
* *
|
|
* public function getTreeAllNodes()
|
|
* {
|
|
*
|
|
* }
|
|
* }
|
|
*
|
|
* 可用方法
|
|
* ```php
|
|
*
|
|
* public function setAllNodes(Collection $nodes)
|
|
* public function getSubLevel($parentId)
|
|
* public function getDescendants($parentId, $depth = 0, $adds = '')
|
|
* public function getLayerOfDescendants($id)
|
|
* public function getSelf($id)
|
|
* public function getParent($id)
|
|
* public function getAncestors($id, $depth = 0)
|
|
*```
|
|
* @package app\common\traits
|
|
*/
|
|
trait MemberTreeTrait
|
|
{
|
|
public $_allNodes = null;
|
|
|
|
protected $treeNodeIdName = 'member_id';
|
|
protected $treeNodeParentIdName = 'parent_id';
|
|
|
|
public $filter = [];
|
|
|
|
/**
|
|
* 数据主ID名.
|
|
*
|
|
* @return string
|
|
*/
|
|
protected function getTreeNodeIdName()
|
|
{
|
|
return property_exists($this, 'treeNodeIdName') ? $this->treeNodeIdName : 'id';
|
|
}
|
|
|
|
/**
|
|
* 数据父ID名.
|
|
*
|
|
* @return string
|
|
*/
|
|
protected function getTreeNodeParentIdName()
|
|
{
|
|
return property_exists($this, 'treeNodeParentIdName') ? $this->treeNodeParentIdName
|
|
: 'parent_id';
|
|
}
|
|
|
|
/**
|
|
* 获取待格式树结构的节点数据.
|
|
*
|
|
* @return mixed
|
|
*/
|
|
final protected function getAllNodes($uniacid)
|
|
{
|
|
if ($this->_allNodes) {
|
|
\Log::debug('------allnodes----');
|
|
return $this->_allNodes;
|
|
}
|
|
if (!method_exists($this, 'getTreeAllNodes')) {
|
|
throw new BadMethodCallException('Method [getTreeAllNodes] does not exist.');
|
|
}
|
|
$data = $this->getTreeAllNodes($uniacid); // 由use的class来实现
|
|
if (!$data instanceof ArrayAccess) {
|
|
throw new InvalidArgumentException('tree data must be a collection');
|
|
}
|
|
// 重置键值
|
|
$this->_allNodes = collect([]);
|
|
foreach ($data as $item) {
|
|
$this->_allNodes->put($item->{$this->getTreeNodeIdName()}, $item);
|
|
}
|
|
return $this->_allNodes;
|
|
}
|
|
|
|
/**
|
|
* 设置 所有节点.
|
|
*
|
|
* @param \Illuminate\Support\Collection $nodes
|
|
*/
|
|
public function setAllNodes(Collection $nodes)
|
|
{
|
|
$this->_allNodes = $nodes;
|
|
}
|
|
|
|
/**
|
|
* 获取子级(仅子代一级).
|
|
*
|
|
* @param mixed $parentId
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getSubLevel($uniacid, $parentId)
|
|
{
|
|
$data = $this->getAllNodes($uniacid);
|
|
$childList = collect([]);
|
|
|
|
foreach ($data as $val) {
|
|
if ($val->{$this->getTreeNodeParentIdName()} == $parentId) {
|
|
|
|
\Log::debug('------add----', [$parentId, $val->member_id]);
|
|
$childList->put($val->{$this->getTreeNodeIdName()}, $val);
|
|
}
|
|
}
|
|
return $childList;
|
|
}
|
|
|
|
/**
|
|
* 获取父级(仅一级).
|
|
*
|
|
* @param mixed $parentId
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getParentLevel($uniacid, $subId)
|
|
{
|
|
$data = $this->getAllNodes($uniacid);
|
|
$parentList = collect([]);
|
|
|
|
if (!empty($data[$subId]) && $subId != $data[$subId]['parent_id'] && $data[$subId]['parent_id'] > 0) {
|
|
\Log::debug('--------list put------', [$subId]);
|
|
$parentList->put($subId, $data[$subId]);
|
|
} else {
|
|
file_put_contents(storage_path("logs/" . date('Y-m-d') . "_batchparent.log"),
|
|
print_r([$subId, $data[$subId]['parent_id'], 'repetition'], 1), FILE_APPEND);
|
|
}
|
|
|
|
return $parentList;
|
|
}
|
|
|
|
/**
|
|
* 获取指定节点的所有后代.
|
|
*
|
|
* @param mixed $parentId
|
|
* @param int $depth
|
|
* @param string $adds
|
|
*
|
|
* @return \Illuminate\Support\Collection
|
|
*/
|
|
public function getDescendants($uniacid, $parentId, $depth = 0, $adds = '')
|
|
{
|
|
static $array;
|
|
if (!$array instanceof ArrayAccess || $depth == 0) {
|
|
$array = collect([]);
|
|
}
|
|
|
|
if (in_array($parentId, $this->filter)) {
|
|
\Log::debug('--------------parentId 已存在----------', [$parentId]);
|
|
\Log::debug('-------------array----------', $array);
|
|
return $array;
|
|
}
|
|
\Log::debug('---------------查询下级---------------', $parentId);
|
|
\Log::debug('---------------层级-------------------', $depth);
|
|
$this->filter[] = $parentId;
|
|
|
|
$child = $this->getSubLevel($uniacid, $parentId);
|
|
\Log::debug('------child----', $child->count());
|
|
if ($child) {
|
|
$nextDepth = $depth + 1;
|
|
|
|
foreach ($child as $val) {
|
|
$val->depth = $depth;
|
|
$array->put($val->{$this->getTreeNodeIdName()}, $val);
|
|
|
|
$this->getDescendants($uniacid,
|
|
$val->{$this->getTreeNodeIdName()},
|
|
$nextDepth
|
|
);
|
|
}
|
|
}
|
|
return $array;
|
|
}
|
|
|
|
public function getNodeParents($uniacid, $subId, $depth = 0)
|
|
{
|
|
static $array;
|
|
|
|
if (!$array instanceof ArrayAccess || $depth == 0) {
|
|
$array = collect([]);
|
|
}
|
|
\Log::debug('--------filter------', [$subId, $this->filter]);
|
|
if (!in_array($subId, $this->filter)) {
|
|
$this->filter[] = $subId;
|
|
|
|
$parent = $this->getParentLevel($uniacid, $subId);
|
|
|
|
if ($parent) {
|
|
$nextDepth = $depth + 1;
|
|
|
|
foreach ($parent as $val) {
|
|
if (!in_array($val->{$this->getTreeNodeParentIdName()}, $this->filter)) {
|
|
$val->depth = $depth;
|
|
|
|
$array->put($val->{$this->getTreeNodeParentIdName()}, $val);
|
|
|
|
$this->getNodeParents($uniacid,
|
|
$val->{$this->getTreeNodeParentIdName()},
|
|
$nextDepth
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return $array;
|
|
}
|
|
|
|
/**
|
|
* 获取指定节点的所有后代(分层级).
|
|
*
|
|
* @param mixed $id
|
|
*
|
|
* @return \Illuminate\Support\Collection
|
|
*/
|
|
public function getLayerOfDescendants($id)
|
|
{
|
|
$child = $this->getSubLevel($id);
|
|
$data = collect([]);
|
|
if ($child) {
|
|
foreach ($child as $val) {
|
|
$val->child = $this->getLayerOfDescendants($val->{$this->getTreeNodeIdName()});
|
|
$data->put($val->{$this->getTreeNodeIdName()}, $val);
|
|
}
|
|
}
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* 获取指定id的数据.
|
|
*
|
|
* @param mixed $id
|
|
*
|
|
* @return mixed
|
|
*/
|
|
public function getSelf($id)
|
|
{
|
|
$data = $this->getAllNodes();
|
|
return $data->get($id);
|
|
}
|
|
|
|
/**
|
|
* 获取父一级节点.
|
|
*
|
|
* @param mixed $id
|
|
*
|
|
* @return mixed
|
|
*/
|
|
public function getParent($id)
|
|
{
|
|
$node = $this->getSelf($id);
|
|
if ($node) {
|
|
$parentId = $node->{$this->getTreeNodeParentIdName()};
|
|
return $this->getSelf($parentId);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取节点的所有祖先.
|
|
*
|
|
* @param int $id
|
|
* @param int $depth
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getAncestors($id, $depth = 0)
|
|
{
|
|
static $array;
|
|
if (!$array instanceof ArrayAccess || $depth == 0) {
|
|
$array = collect([]);
|
|
}
|
|
$parent = $this->getParent($id);
|
|
if ($parent) {
|
|
$nextDepth = $depth + 1;
|
|
$array->prepend($parent); // 添加到开头
|
|
$this->getAncestors($parent->{$this->getTreeNodeIdName()}, $nextDepth);
|
|
}
|
|
return $array;
|
|
}
|
|
|
|
public function chkNodeParents($uniacid, $subId, $depth = 0)
|
|
{
|
|
static $array;
|
|
|
|
if (!$array instanceof ArrayAccess || $depth == 0) {
|
|
$array = collect([]);
|
|
}
|
|
|
|
if (!in_array($subId, $this->filter)) {
|
|
$this->filter[] = $subId;
|
|
|
|
$parent = $this->chkParentLevel($uniacid, $subId);
|
|
|
|
if ($parent) {
|
|
$nextDepth = $depth + 1;
|
|
|
|
foreach ($parent as $val) {
|
|
if (!in_array($val->{$this->getTreeNodeParentIdName()}, $this->filter)) {
|
|
$val->depth = $depth;
|
|
|
|
$array->put($val->{$this->getTreeNodeParentIdName()}, $val);
|
|
|
|
$this->chkNodeParents($uniacid,
|
|
$val->{$this->getTreeNodeParentIdName()},
|
|
$nextDepth
|
|
);
|
|
}
|
|
|
|
}
|
|
}
|
|
} else {
|
|
\Log::debug('---------重复上级------', [$subId, $this->filter]);
|
|
file_put_contents(storage_path("logs/" . date('Y-m-d') . "-parenterror.log"), print_r($subId . ',', 1),
|
|
FILE_APPEND);
|
|
}
|
|
}
|
|
|
|
public function chkParentLevel($uniacid, $subId)
|
|
{
|
|
$data = $this->getAllNodes($uniacid);
|
|
$parentList = collect([]);
|
|
|
|
if (!empty($data[$subId]) && $subId != $data[$subId]['parent_id'] && $data[$subId]['parent_id'] > 0) {
|
|
\Log::debug('---------list put------', [$subId]);
|
|
$parentList->put($subId, $data[$subId]);
|
|
}
|
|
|
|
return $parentList;
|
|
}
|
|
|
|
} |