MemberTreeTrait.php 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * Author: 芸众商城 www.yunzshop.com
  5. * Date: 16/03/2017
  6. * Time: 08:58
  7. */
  8. namespace app\common\traits;
  9. use app\common\services\member\MemberRelation;
  10. use ArrayAccess;
  11. use BadMethodCallException;
  12. use Illuminate\Support\Collection;
  13. use InvalidArgumentException;
  14. /**
  15. * Class TreeTrait
  16. *
  17. * 使用
  18. * <?php
  19. * namespace app\common\models;
  20. * use app\common\traits\TreeTrait;
  21. *
  22. * class MyClass
  23. * {
  24. * use TreeTrait;
  25. *
  26. * // 自定义属性(可选)
  27. * protected $treeNodeIdName = 'id';
  28. * protected $treeNodeParentIdName = 'parent_id';
  29. * /**
  30. * * 获取待处理的原始节点数据
  31. * *
  32. * * 必须实现
  33. * *
  34. * * return \Illuminate\Support\Collection
  35. * *
  36. * public function getTreeAllNodes()
  37. * {
  38. *
  39. * }
  40. * }
  41. *
  42. * 可用方法
  43. * ```php
  44. *
  45. * public function setAllNodes(Collection $nodes)
  46. * public function getSubLevel($parentId)
  47. * public function getDescendants($parentId, $depth = 0, $adds = '')
  48. * public function getLayerOfDescendants($id)
  49. * public function getSelf($id)
  50. * public function getParent($id)
  51. * public function getAncestors($id, $depth = 0)
  52. *```
  53. * @package app\common\traits
  54. */
  55. trait MemberTreeTrait
  56. {
  57. public $_allNodes = null;
  58. protected $treeNodeIdName = 'member_id';
  59. protected $treeNodeParentIdName = 'parent_id';
  60. public $filter = [];
  61. /**
  62. * 数据主ID名.
  63. *
  64. * @return string
  65. */
  66. protected function getTreeNodeIdName()
  67. {
  68. return property_exists($this, 'treeNodeIdName') ? $this->treeNodeIdName : 'id';
  69. }
  70. /**
  71. * 数据父ID名.
  72. *
  73. * @return string
  74. */
  75. protected function getTreeNodeParentIdName()
  76. {
  77. return property_exists($this, 'treeNodeParentIdName') ? $this->treeNodeParentIdName
  78. : 'parent_id';
  79. }
  80. /**
  81. * 获取待格式树结构的节点数据.
  82. *
  83. * @return mixed
  84. */
  85. final protected function getAllNodes($uniacid)
  86. {
  87. if ($this->_allNodes) {
  88. \Log::debug('------allnodes----');
  89. return $this->_allNodes;
  90. }
  91. if (!method_exists($this, 'getTreeAllNodes')) {
  92. throw new BadMethodCallException('Method [getTreeAllNodes] does not exist.');
  93. }
  94. $data = $this->getTreeAllNodes($uniacid); // 由use的class来实现
  95. if (!$data instanceof ArrayAccess) {
  96. throw new InvalidArgumentException('tree data must be a collection');
  97. }
  98. // 重置键值
  99. $this->_allNodes = collect([]);
  100. foreach ($data as $item) {
  101. $this->_allNodes->put($item->{$this->getTreeNodeIdName()}, $item);
  102. }
  103. return $this->_allNodes;
  104. }
  105. /**
  106. * 设置 所有节点.
  107. *
  108. * @param \Illuminate\Support\Collection $nodes
  109. */
  110. public function setAllNodes(Collection $nodes)
  111. {
  112. $this->_allNodes = $nodes;
  113. }
  114. /**
  115. * 获取子级(仅子代一级).
  116. *
  117. * @param mixed $parentId
  118. *
  119. * @return array
  120. */
  121. public function getSubLevel($uniacid, $parentId)
  122. {
  123. $data = $this->getAllNodes($uniacid);
  124. $childList = collect([]);
  125. foreach ($data as $val) {
  126. if ($val->{$this->getTreeNodeParentIdName()} == $parentId) {
  127. \Log::debug('------add----', [$parentId, $val->member_id]);
  128. $childList->put($val->{$this->getTreeNodeIdName()}, $val);
  129. }
  130. }
  131. return $childList;
  132. }
  133. /**
  134. * 获取父级(仅一级).
  135. *
  136. * @param mixed $parentId
  137. *
  138. * @return array
  139. */
  140. public function getParentLevel($uniacid, $subId)
  141. {
  142. $data = $this->getAllNodes($uniacid);
  143. $parentList = collect([]);
  144. if (!empty($data[$subId]) && $subId != $data[$subId]['parent_id'] && $data[$subId]['parent_id'] > 0) {
  145. \Log::debug('--------list put------', [$subId]);
  146. $parentList->put($subId, $data[$subId]);
  147. } else {
  148. file_put_contents(storage_path("logs/" . date('Y-m-d') . "_batchparent.log"),
  149. print_r([$subId, $data[$subId]['parent_id'], 'repetition'], 1), FILE_APPEND);
  150. }
  151. return $parentList;
  152. }
  153. /**
  154. * 获取指定节点的所有后代.
  155. *
  156. * @param mixed $parentId
  157. * @param int $depth
  158. * @param string $adds
  159. *
  160. * @return \Illuminate\Support\Collection
  161. */
  162. public function getDescendants($uniacid, $parentId, $depth = 0, $adds = '')
  163. {
  164. static $array;
  165. if (!$array instanceof ArrayAccess || $depth == 0) {
  166. $array = collect([]);
  167. }
  168. if (in_array($parentId, $this->filter)) {
  169. \Log::debug('--------------parentId 已存在----------', [$parentId]);
  170. \Log::debug('-------------array----------', $array);
  171. return $array;
  172. }
  173. \Log::debug('---------------查询下级---------------', $parentId);
  174. \Log::debug('---------------层级-------------------', $depth);
  175. $this->filter[] = $parentId;
  176. $child = $this->getSubLevel($uniacid, $parentId);
  177. \Log::debug('------child----', $child->count());
  178. if ($child) {
  179. $nextDepth = $depth + 1;
  180. foreach ($child as $val) {
  181. $val->depth = $depth;
  182. $array->put($val->{$this->getTreeNodeIdName()}, $val);
  183. $this->getDescendants($uniacid,
  184. $val->{$this->getTreeNodeIdName()},
  185. $nextDepth
  186. );
  187. }
  188. }
  189. return $array;
  190. }
  191. public function getNodeParents($uniacid, $subId, $depth = 0)
  192. {
  193. static $array;
  194. if (!$array instanceof ArrayAccess || $depth == 0) {
  195. $array = collect([]);
  196. }
  197. \Log::debug('--------filter------', [$subId, $this->filter]);
  198. if (!in_array($subId, $this->filter)) {
  199. $this->filter[] = $subId;
  200. $parent = $this->getParentLevel($uniacid, $subId);
  201. if ($parent) {
  202. $nextDepth = $depth + 1;
  203. foreach ($parent as $val) {
  204. if (!in_array($val->{$this->getTreeNodeParentIdName()}, $this->filter)) {
  205. $val->depth = $depth;
  206. $array->put($val->{$this->getTreeNodeParentIdName()}, $val);
  207. $this->getNodeParents($uniacid,
  208. $val->{$this->getTreeNodeParentIdName()},
  209. $nextDepth
  210. );
  211. }
  212. }
  213. }
  214. }
  215. return $array;
  216. }
  217. /**
  218. * 获取指定节点的所有后代(分层级).
  219. *
  220. * @param mixed $id
  221. *
  222. * @return \Illuminate\Support\Collection
  223. */
  224. public function getLayerOfDescendants($id)
  225. {
  226. $child = $this->getSubLevel($id);
  227. $data = collect([]);
  228. if ($child) {
  229. foreach ($child as $val) {
  230. $val->child = $this->getLayerOfDescendants($val->{$this->getTreeNodeIdName()});
  231. $data->put($val->{$this->getTreeNodeIdName()}, $val);
  232. }
  233. }
  234. return $data;
  235. }
  236. /**
  237. * 获取指定id的数据.
  238. *
  239. * @param mixed $id
  240. *
  241. * @return mixed
  242. */
  243. public function getSelf($id)
  244. {
  245. $data = $this->getAllNodes();
  246. return $data->get($id);
  247. }
  248. /**
  249. * 获取父一级节点.
  250. *
  251. * @param mixed $id
  252. *
  253. * @return mixed
  254. */
  255. public function getParent($id)
  256. {
  257. $node = $this->getSelf($id);
  258. if ($node) {
  259. $parentId = $node->{$this->getTreeNodeParentIdName()};
  260. return $this->getSelf($parentId);
  261. }
  262. }
  263. /**
  264. * 获取节点的所有祖先.
  265. *
  266. * @param int $id
  267. * @param int $depth
  268. *
  269. * @return array
  270. */
  271. public function getAncestors($id, $depth = 0)
  272. {
  273. static $array;
  274. if (!$array instanceof ArrayAccess || $depth == 0) {
  275. $array = collect([]);
  276. }
  277. $parent = $this->getParent($id);
  278. if ($parent) {
  279. $nextDepth = $depth + 1;
  280. $array->prepend($parent); // 添加到开头
  281. $this->getAncestors($parent->{$this->getTreeNodeIdName()}, $nextDepth);
  282. }
  283. return $array;
  284. }
  285. public function chkNodeParents($uniacid, $subId, $depth = 0)
  286. {
  287. static $array;
  288. if (!$array instanceof ArrayAccess || $depth == 0) {
  289. $array = collect([]);
  290. }
  291. if (!in_array($subId, $this->filter)) {
  292. $this->filter[] = $subId;
  293. $parent = $this->chkParentLevel($uniacid, $subId);
  294. if ($parent) {
  295. $nextDepth = $depth + 1;
  296. foreach ($parent as $val) {
  297. if (!in_array($val->{$this->getTreeNodeParentIdName()}, $this->filter)) {
  298. $val->depth = $depth;
  299. $array->put($val->{$this->getTreeNodeParentIdName()}, $val);
  300. $this->chkNodeParents($uniacid,
  301. $val->{$this->getTreeNodeParentIdName()},
  302. $nextDepth
  303. );
  304. }
  305. }
  306. }
  307. } else {
  308. \Log::debug('---------重复上级------', [$subId, $this->filter]);
  309. file_put_contents(storage_path("logs/" . date('Y-m-d') . "-parenterror.log"), print_r($subId . ',', 1),
  310. FILE_APPEND);
  311. }
  312. }
  313. public function chkParentLevel($uniacid, $subId)
  314. {
  315. $data = $this->getAllNodes($uniacid);
  316. $parentList = collect([]);
  317. if (!empty($data[$subId]) && $subId != $data[$subId]['parent_id'] && $data[$subId]['parent_id'] > 0) {
  318. \Log::debug('---------list put------', [$subId]);
  319. $parentList->put($subId, $data[$subId]);
  320. }
  321. return $parentList;
  322. }
  323. }