owner->innerJoinWith('treePathsChild treePathsChild', $eagerLoading) ->andWhere(['treePathsChild.parent_id' => $ownerId]); if (!$withParent) { $this->owner ->andWhere(['!=', 'treePathsChild.child_id', $ownerId]); } if ($depth !== null) { $this->depthCheck($depth); /** @var self $subQuery */ $subQuery = ($this->owner->modelClass::find()) ->select(new Expression('treePathOwner.child_level + :depth', [':depth' => $depth])) ->owner($ownerId); $this->owner ->andWhere(['<=', 'treePathsChild.child_level', $subQuery]); } return $this->owner; } /** * 获取元素的所有父节点 * * @param int $ownerId * @param bool|false $withChild * @param int|null $depth * @param bool|false $eagerLoading * @return ActiveQuery * @throws LogicException */ public function parents( int $ownerId, bool $withChild = false, ?int $depth = null, bool $eagerLoading = false ): ActiveQuery { $this->owner ->innerJoinWith('treePathsParent treePathsParent', $eagerLoading) ->andWhere(['treePathsParent.child_id' => $ownerId]); if (!$withChild) { $this->owner ->andWhere(['!=', 'treePathsParent.parent_id', $ownerId]); } if ($depth !== null) { $this->depthCheck($depth); /** @var self $subQuery */ $subQuery = ($this->owner->modelClass::find()) ->select( new Expression( 'IF(treePathOwner.child_level <= :depth, 1, treePathOwner.child_level - :depth)', [':depth' => $depth] ) ) ->owner($ownerId); $this->owner ->andWhere(['>=', 'treePathsParent.parent_level', $subQuery]); } return $this->owner; } /** * 获取元素父节点 * * @param int $ownerId * @param bool $eagerLoading * @return ActiveQuery */ public function parent(int $ownerId, bool $eagerLoading = false): ActiveQuery { return $this->owner ->innerJoinWith('treePathsNearestParent treePathsNearestParent', $eagerLoading) ->andWhere(['treePathsNearestParent.parent_id' => $ownerId]) ->andWhere(['treePathsNearestParent.child_id' => $ownerId]); } /** * 获取所有根节点 * * @param bool $eagerLoading * @return ActiveQuery */ public function roots(bool $eagerLoading = false): ActiveQuery { return $this->owner ->innerJoinWith('treePathsParent treePathsParent', $eagerLoading) ->andWhere(['treePathsParent.nearest_parent_id' => 0]); } /** * 获取元素直系子节点 * * @param int $ownerId * @param bool $eagerLoading * @return ActiveQuery */ public function nearestChilds(int $ownerId, bool $eagerLoading = false): ActiveQuery { return $this->owner ->innerJoinWith('treePathsChild treePathsChild', $eagerLoading) ->andWhere(['treePathsChild.nearest_parent_id' => $ownerId]) ->andWhere(['treePathsChild.parent_id' => $ownerId]); } /** * 查询元素条件 * * @param int $ownerId * @param bool $eagerLoading * @return ActiveQuery */ public function owner(int $ownerId, bool $eagerLoading = false): ActiveQuery { return $this->owner ->innerJoinWith('treePathOwner treePathOwner', $eagerLoading) ->andWhere(['treePathOwner.parent_id' => $ownerId]) ->andWhere(['treePathOwner.child_id' => $ownerId]); } }