Документация

Tree: выборки по дереву

Методы обхода DevBx\Core\Internals\Tree. Все возвращают выборку DataManager, и все принимают привычный $parametersselect, filter, order, limit.

Вниз по дереву

php
$rs = CategoryTable::getChildren($id, ['select' => ['ID', 'NAME']]);   // прямые потомки
$rs = CategoryTable::getChildren(0);                                    // первый уровень дерева

$rs = CategoryTable::getSubTree($id);                                   // узел со всеми потомками
$rs = CategoryTable::getSubTree(0);                                     // всё дерево целиком

getSubTree по умолчанию сортирует по левой границе — то есть в порядке обхода, в котором родитель идёт перед своими потомками. Это ровно тот порядок, который нужен для вывода дерева списком.

Вверх по дереву

php
$rs = CategoryTable::getPathToNode($id, ['select' => ['ID', 'NAME']]);
$rs = CategoryTable::getPathToNode($id, $parameters, ['SHOW_LEAF' => false]);

Цепочка родителей от корня к узлу, порядок — от корня. SHOW_LEAF => false убирает из ответа сам узел: так удобно строить хлебные крошки, где последнее звено не ссылка.

Родственные методы:

Метод Что делает
getPathToNodeByCondition($filter, $parameters, $behaviour) то же, но узел ищется фильтром, а не по номеру
getPathToMultipleNodes($nodeInfo, $parameters, $behaviour) цепочки сразу к нескольким узлам, ответ — DB\ArrayResult
getDeepestCommonParent($nodeInfo, $parameters) ближайший общий родитель набора узлов

$nodeInfo у последних двух — массив массивов, в каждом должны быть LEFT_MARGIN и RIGHT_MARGIN. Это не номера узлов: границы вызывающий читает сам, зато метод не идёт за ними в базу.

Ветка с раскрытыми уровнями

php
$rs = CategoryTable::getParentTree($id);
$rs = CategoryTable::getParentTree($id, [], ['SHOW_CHILDREN' => false, 'START_FROM' => $rootId]);

Отдаёт цепочку родителей вместе с соседями на каждом уровне — то, что нужно дереву в интерфейсе, когда раскрыт один узел, а остальные ветки свёрнуты до своего уровня. SHOW_CHILDREN => false убирает потомков самого узла, START_FROM начинает раскрытие не от корня, а от указанного узла.

Проверки и подзапрос

php
CategoryTable::checkNodeIsParentOfNodeById($parentId, $childId);
CategoryTable::checkNodeIsParentOfNodeById($parentId, $childId, ['CHECK_DIRECT' => true]);

$sql = CategoryTable::getSubtreeRangeSqlForNode($id);

Первый отвечает, является ли узел родителем другого; с CHECK_DIRECT — только прямым. Узла нет — SystemException.

Второй отдаёт подзапрос с номерами поддерева, чтобы подставить его в чужой фильтр. Помечен как служебный: подпись может измениться.

Что учесть

Свой фильтр по границам будет затёрт. Методы дописывают в $parameters['filter'] условия по LEFT_MARGIN, RIGHT_MARGIN и DEPTH_LEVEL. Своё условие по этим полям в том же фильтре не переживёт вызова.

Порядок задаётся не везде. getSubTree, getPathToNode и getParentTree ставят сортировку по левой границе, если своя не задана. У getChildren умолчания нет — порядок будет тот, что вернёт база.

У класса есть свои expect*-методы. expectInteger, expectIntegerPositive и другие повторяют DevBx\Core\Assert и объявлены прямо в Tree — на них опираются его собственные проверки. В своём коде берите Assert: у него это и есть ответственность.