Дерево поведения
Придает таблице, к которой оно прикреплено, поведение, подобное вложенным множествам, и предоставляет методы для управления и извлечения информации из полученной иерархической структуры.
Таблицы, к которым прикреплено это поведение, должны содержать столбец, ссылающийся на родительскую строку, и еще два числовых столбца (lft и rght), где неявный порядок будет кэширован.
Для получения дополнительной информации о том, что такое вложенное множество и как оно работает, обратитесь к https://www.sitepoint.com/hierarchical-data-database-2/
- Cake\ORM\Behavior реализует Cake\Event\EventListenerInterface использует Cake\Core\InstanceConfigTrait
-
Cake\ORM\Behavior\TreeBehavior
Краткое описание свойств
-
$_defaultConfigprotectedКонфигурация по умолчаниюarray -
$_primaryKeyprotectedКэшированная копия первого столбца первичного ключа таблицы.string
Унаследованные свойства
Краткое описание методов
- _ensureFields() protected
Обеспечивает, что предоставленная сущность содержит непустые значения для полей left и right
- _getMax() protectedВозвращает максимальное значение индекса в таблице.
- _getNode() protectedВозвращает единственный узел из дерева по его первичному ключу
- _getPrimaryKey() protectedВозвращает единственное строковое значение, представляющее первичный ключ присоединенной таблицы
- _moveDown() protectedВспомогательная функция, используемая с фактическим кодом для moveDown
- _moveUp() protectedВспомогательная функция, используемая с фактическим кодом для moveUp
- _recoverTree() protectedРекурсивный метод, используемый для восстановления одного уровня дерева
- _removeFromTree() protectedВспомогательная функция, содержащая фактический код для removeFromTree
- _scope() protected
Изменяет переданный запрос таким образом, чтобы он возвращал только отфильтрованные записи, как определено в конфигурации дерева.
- _setAsRoot() protected
Обновляет поля left и right для переданной сущности, чтобы ее можно было установить в качестве нового корня в дереве. Также изменяет порядок в остальной части дерева, чтобы структура оставалась корректной
- _setChildrenLevel() protectedУстановить уровень для потомков.
- _setParent() protected
Устанавливает правильные значения left и right для переданной сущности, чтобы ее можно было обновить до нового родителя. Также создает пробел в дереве, чтобы перемещение узла можно было выполнить без повреждения структуры.
- _sync() protected
Вспомогательная функция, используемая для автоматического изменения значений полей left и right на определенную величину, соответствующую переданным условиям
- _unmarkInternalTree() protected
Вспомогательный метод, используемый для изменения знака полей left и right, которые меньше 0. Они были установлены в отрицательные значения ранее, чтобы их абсолютное значение не менялось во время выполнения других преобразований дерева.
- afterSave() publicПрослушиватель после сохранения.
- beforeDelete() publicТакже удаляет узлы в поддереве удаляемой сущности
- beforeSave() public
Прослушиватель перед сохранением. Прозрачно управляет установкой полей lft и rght, если поле parent включено в параметры, которые необходимо сохранить.
- childCount() publicПолучить количество дочерних узлов.
- findChildren() publicПолучить дочерние узлы текущей модели
- findPath() public
Специальный метод поиска, который можно использовать для получения списка узлов от корня до определенного узла в дереве. Для этого специального поиска необходимо, чтобы ключ 'for' передавался в параметрах, содержащих идентификатор узла, для которого требуется получить путь.
- findTreeList() public
Получает представление элементов в дереве в виде плоского списка, где ключи — это первичный ключ таблицы, а значения — поле отображения таблицы. Значения предваряются префиксом для визуального обозначения относительной глубины в дереве.
- formatTreeList() public
Форматирует запрос как плоский список, где ключи — первичный ключ таблицы, а значения — поле отображения таблицы. Значения предваряются префиксом для визуального обозначения относительной глубины в дереве.
- getLevel() publicВозвращает уровень глубины узла в дереве.
- initialize() publicМетод подключения конструктора.
- moveDown() publicПереупорядочивает узел без изменения родителя.
- moveUp() publicПереупорядочивает узел без изменения родителя.
- recover() public
Восстанавливает значения столбцов lft и right из иерархии, определенной столбцом родителя.
- removeFromTree() public
Удаляет текущий узел из дерева, размещая его как новый корень и перемещая всех потомков на один уровень вверх.
Подробное описание методов
_ensureFields()source protected
_ensureFields( Cake\Datasource\EntityInterface $entity )
Обеспечивает, что предоставленная сущность содержит непустые значения для полей left и right
Параметры
-
Cake\Datasource\EntityInterface$entity - Сущность, для которой необходимо проверить поля
_getMax()source protected
_getMax( )
Возвращает максимальное значение индекса в таблице.
Возвращает
integer_getNode()source protected
_getNode( mixed $id )
Возвращает единственный узел из дерева по его первичному ключу
Параметры
- mixed
$id - Идентификатор записи.
Возвращает
Cake\Datasource\EntityInterfaceВыбрасывает
Cake\Datasource\Exception\RecordNotFoundExceptionЕсли узел не найден
_getPrimaryKey()source protected
_getPrimaryKey( )
Возвращает единственное строковое значение, представляющее первичный ключ присоединенной таблицы
Возвращает
string_moveDown()source protected
_moveDown( Cake\Datasource\EntityInterface $node , integer|boolean $number )
Вспомогательная функция, используемая в действительном коде для moveDown
Параметры
-
Cake\Datasource\EntityInterface$node - Узел, который нужно переместить
- integer|boolean
$number - Количество позиций, на которое нужно переместить узел, или true для перемещения в последнюю позицию
Возвращает
Cake\Datasource\EntityInterface|boolean$node Узел после перемещения или false при ошибке
Исключения
Cake\Datasource\Exception\RecordNotFoundExceptionПри отсутствии узла
_moveUp()source protected
_moveUp( Cake\Datasource\EntityInterface $node , integer|boolean $number )
Вспомогательная функция, используемая в действительном коде для moveUp
Параметры
-
Cake\Datasource\EntityInterface$node - Узел, который нужно переместить
- integer|boolean
$number - Количество позиций, на которое нужно переместить узел, или true для перемещения в первую позицию
Возвращает
Cake\Datasource\EntityInterface|boolean$node Узел после перемещения или false при ошибке
Исключения
Cake\Datasource\Exception\RecordNotFoundExceptionПри отсутствии узла
_recoverTree()source protected
_recoverTree( integer $counter 0 , mixed $parentId null , integer $level -1 )
Рекурсивный метод, используемый для восстановления одного уровня дерева
Параметры
- integer
$counterнеобязательно 0 - Значение последнего левого столбца, которое было присвоено
- mixed
$parentIdнеобязательно null - Идентификатор родителя уровня, который нужно восстановить
- integer
$levelнеобязательно -1 - Уровень узла
Возвращает
integerСледующее значение для использования в левом столбце
_removeFromTree()source protected
_removeFromTree( Cake\Datasource\EntityInterface $node )
Вспомогательная функция, содержащая фактический код для removeFromTree
Параметры
-
Cake\Datasource\EntityInterface$node - Узел, который нужно удалить из дерева
Возвращает
Cake\Datasource\EntityInterface|falseУзел после удаления из дерева или false при ошибке
_scope()source protected
_scope( Cake\ORM\Query $query )
Изменяет переданный запрос, чтобы он возвращал только отфильтрованные записи, как определено в настройках дерева.
Параметры
-
Cake\ORM\Query$query - Запрос, который нужно изменить
Возвращает
Cake\ORM\Query_setAsRoot()source protected
_setAsRoot( Cake\Datasource\EntityInterface $entity )
Обновляет левые и правые столбцы для переданной сущности, чтобы она могла быть установлена как новый корень в дереве. Также изменяет порядок в остальной части дерева, чтобы структура оставалась валидной
Параметры
-
Cake\Datasource\EntityInterface$entity - Сущность, которую нужно установить как новый корень
_setChildrenLevel()source protected
_setChildrenLevel( Cake\Datasource\EntityInterface $entity )
Устанавливает уровень для потомков.
Параметры
-
Cake\Datasource\EntityInterface$entity - Сущность, потомки которой нужно обновить.
_setParent()source protected
_setParent( Cake\Datasource\EntityInterface $entity , mixed $parent )
Устанавливает правильные значения левого и правого столбцов для переданной сущности, чтобы она могла быть обновлена до нового родителя. Также создаёт отверстие в дереве, чтобы перемещение узла можно было выполнить, не нарушая структуру.
Параметры
-
Cake\Datasource\EntityInterface$entity - Сущность, которую нужно переместить к новому родителю
- mixed
$parent - Идентификатор родителя, который нужно установить
Исключения
RuntimeExceptionЕсли родитель, который нужно установить для сущности, некорректен
_sync()source protected
_sync( integer $shift , string $dir , string $conditions , boolean $mark false )
Вспомогательная функция, используемая для автоматического изменения значения столбцов left и right на определённую величину, соответствующую переданным условиям
Параметры
- integer
$shift - Значение, используемое для изменения столбцов left и right
- string
$dir - Оператор, используемый для сдвига значения (+/-)
- string
$conditions SQL фрагмент, используемый для сравнения left или right с ним.
- boolean
$markнеобязательно false указывает, нужно ли пометить обновлённые значения, чтобы они не могли быть изменены последующими вызовами этой функции.
_unmarkInternalTree()source protected
_unmarkInternalTree( )
Вспомогательный метод, используемый для изменения знака столбцов left и right, которые меньше 0. Они были установлены в отрицательные значения ранее, чтобы их абсолютное значение не изменялось при выполнении других преобразований дерева.
afterSave()source public
afterSave( Cake\Event\Event $event , Cake\Datasource\EntityInterface $entity )
Обработчик после сохранения.
Управляет обновлением уровня потомков текущей сохранённой сущности.
Параметры
-
Cake\Event\Event$event - Событие afterSave, которое было сгенерировано
-
Cake\Datasource\EntityInterface$entity - сущность, которая будет сохранена
beforeDelete()source public
beforeDelete( Cake\Event\Event $event , Cake\Datasource\EntityInterface $entity )
Также удаляет узлы в поддереве сущности, подлежащей удалению
Параметры
-
Cake\Event\Event$event - Событие beforeDelete, которое было сгенерировано
-
Cake\Datasource\EntityInterface$entity - Сущность, которая будет сохранена
beforeSave()source public
beforeSave( Cake\Event\Event $event , Cake\Datasource\EntityInterface $entity )
Обработчик до сохранения. Прозрачно управляет установкой полей lft и rght, если поле parent включено в параметры, подлежащие сохранению.
Параметры
-
Cake\Event\Event$event - Событие beforeSave, которое было сгенерировано
-
Cake\Datasource\EntityInterface$entity - Сущность, которая будет сохранена
Исключения
RuntimeExceptionЕсли родитель, который нужно установить для узла, некорректен
childCount()source public
childCount( Cake\Datasource\EntityInterface $node , boolean $direct false )
Получение количества дочерних узлов.
Параметры
-
Cake\Datasource\EntityInterface$node - Сущность, для которой нужно посчитать количество дочерних элементов
- boolean
$directнеобязательно false указывает, нужно ли подсчитать все узлы в поддереве или только прямых потомков
Возвращает
integerКоличество дочерних узлов.
findChildren()source public
findChildren( Cake\ORM\Query $query , array $options )
Получение дочерних узлов текущей модели
Доступные параметры:
- for: Идентификатор записи для чтения.
- direct: Булево значение, указывающее, возвращать только прямых (true) или все (false) потомки, по умолчанию false (все потомки).
Если параметр direct установлен в true, возвращаются только прямые потомки (на основе поля parent_id)
Параметры
-
Cake\ORM\Query$query - Запрос.
- array
$options - Массив параметров, как описано выше
Возвращает
Cake\ORM\QueryИсключения
InvalidArgumentExceptionЕсли ключ 'for' не передан в $options
findPath()source public
findPath( Cake\ORM\Query $query , array $options )
Пользовательский метод поиска, который может быть использован для возвращения списка узлов от корня до конкретного узла в дереве. Этот пользовательский поиск требует, чтобы ключ 'for' был передан в опциях, содержащих идентификатор узла, для которого нужно получить путь.
Параметры
-
Cake\ORM\Query$query - Конструируемый запрос для изменения
- массив
$options - список опций для запроса
Возвращает
Cake\ORM\QueryИсключения
InvalidArgumentExceptionЕсли ключ 'for' отсутствует в опциях
findTreeList()source public
findTreeList( Cake\ORM\Query $query , array $options )
Получает представление элементов в дереве в виде плоского списка, где ключи — первичный ключ таблицы, а значения — поле отображения таблицы. Значения имеют префиксы для визуального обозначения относительной глубины в дереве.
Опции
- keyPath: Путь с точками для извлечения поля, которое будет использоваться в качестве ключа массива, или замыкание для возврата ключа из предоставленной строки.
- valuePath: Путь с точками для извлечения поля, которое будет использоваться в качестве значения массива, или замыкание для возврата значения из предоставленной строки.
- spacer: Строка, используемая в качестве префикса для обозначения глубины в дереве для каждого элемента
Параметры
-
Cake\ORM\Query$query - Запрос.
- массив
$options - Массив опций, как описано выше.
Возвращает
Cake\ORM\QueryformatTreeList()source public
formatTreeList( Cake\ORM\Query $query , array $options [] )
Форматирует запрос в виде плоского списка, где ключи — первичный ключ таблицы, а значения — поле отображения таблицы. Значения имеют префиксы для визуального обозначения относительной глубины в дереве.
Опции
- keyPath: Путь с точками до поля, которое будет ключом результативного массива, или замыкание для возвращения ключа из предоставленной строки.
- valuePath: Путь с точками до поля, являющегося значением массива, или замыкание для возвращения значения из предоставленной строки.
- spacer: Строка, используемая в качестве префикса для обозначения глубины в дереве для каждого элемента.
Параметры
-
Cake\ORM\Query$query - Объект запроса для форматирования.
- массив
$optionsнеобязательно [] - Массив опций, как описано выше.
Возвращает
Cake\ORM\QueryРасширенный запрос.
getLevel()source public
getLevel( integer|string|Cake\Datasource\EntityInterface $entity )
Возвращает уровень глубины узла в дереве.
Параметры
- целое число|строка|
Cake\Datasource\EntityInterface$entity - Сущность или первичный ключ, для которого нужно получить уровень.
Возвращает
целое число|логическое значениеЦелое число уровня или ложь, если узел не существует.
initialize()source public
initialize( array $config )
Метод обратного вызова конструктора.
Параметры
- массив
$config - Настройки конфигурации, предоставленные для этого поведения.
Переопределяет
Cake\ORM\Behavior::initialize() moveDown()source public
moveDown( Cake\Datasource\EntityInterface $node , integer|boolean $number 1 )
Переупорядочивает узел, не изменяя родителя.
Если узел является последним дочерним элементом или является узлом верхнего уровня без последующего узла, этот метод вернет false
Параметры
-
Cake\Datasource\EntityInterface$node - Узел, который нужно переместить
- целое число|логическое значение
$numberнеобязательно 1 - Сколько позиций переместить узел или true для перемещения в последнюю позицию
Возвращает
Cake\Datasource\EntityInterface|логическое значениесущность после перемещения или false при ошибке
Исключения
Cake\Datasource\Exception\RecordNotFoundExceptionКогда узел не был найден
moveUp()source public
moveUp( Cake\Datasource\EntityInterface $node , integer|boolean $number 1 )
Переупорядочивает узел, не изменяя его родителя.
Если узел является первым дочерним элементом или является узлом верхнего уровня без предыдущего узла, этот метод вернет false
Параметры
-
Cake\Datasource\EntityInterface$node - Узел, который нужно переместить
- целое число|логическое значение
$numberнеобязательно 1 - Сколько позиций переместить узел или true для перемещения в первую позицию
Возвращает
Cake\Datasource\EntityInterface|логическое значение$node Узел после перемещения или false при ошибке
Исключения
Cake\Datasource\Exception\RecordNotFoundExceptionКогда узел не был найден
recover()source public
recover( )
Восстанавливает значения столбцов lft и right из иерархии, определенной столбцом родителя.
removeFromTree()source public
removeFromTree( Cake\Datasource\EntityInterface $node )
Удаляет текущий узел из дерева, размещая его как новый корень и перемещая всех дочерних элементов на один уровень выше.
Обратите внимание, что узел не будет удален, а только перемещен из текущего положения, без перемещения его дочерних элементов вместе с ним.
Параметры
-
Cake\Datasource\EntityInterface$node - Узел, который нужно удалить из дерева
Возвращает
Cake\Datasource\EntityInterface|falseузел после удаления из дерева или false при ошибке
Методы, унаследованные от Cake\ORM\Behavior
__construct()source public
__construct( Cake\ORM\Table $table , array $config [] )
Конструктор
Объединяет конфигурацию с конфигурацией по умолчанию и сохраняет в свойстве config
Параметры
-
Cake\ORM\Table$table - Таблица, к которой прикреплено это поведение.
- массив
$configнеобязательно [] - Конфигурация для этого поведения.
_reflectionCache()source protected
_reflectionCache( )
Получает методы, реализованные этим поведением
Использует метод implementedEvents() для исключения методов обратного вызова. Методы, начинающиеся с _ будут игнорироваться, как и методы, объявленные в Cake\ORM\Behavior
Возвращает
массив_resolveMethodAliases()source protected
_resolveMethodAliases( string $key , array $defaults , array $config )
Удаляет алиасы методов, которые в противном случае были бы дублированы пользовательской конфигурацией.
Параметры
- строка
$key - Ключ для фильтрации.
- массив
$defaults - Карты методов по умолчанию.
- массив
$config - Настраиваемые карты методов.
Возвращает
массивСписок данных конфигурации без дублирования.
getTable()source public
getTable( )
Получить экземпляр таблицы, к которому привязано это поведение.
Возвращает
Cake\ORM\TableСвязанный экземпляр таблицы.
implementedEvents()source public
implementedEvents( )
Получает обратные вызовы модели, которыми интересуется это поведение.
Определяя один из методов обратного вызова, предполагается, что поведение заинтересовано в соответствующем событии.
Переопределите этот метод, если вам нужно добавить слушателей событий, отличных от стандартных. Или если вы хотите, чтобы ваше поведение отслеживало события, отличные от стандартных.
Возвращает
массивРеализация
Cake\Event\EventListenerInterface::implementedEvents() implementedFinders()source public
implementedFinders( )
implementedFinders
Предоставляет отображение «псевдоним» -> «имя метода», показывающее, какие поискеры реализует поведение. Пример:
[ 'this' => 'findThis', 'alias' => 'findMethodName' ]
В приведенном выше примере вызов $Table->find('this') вызовет $Behavior->findThis(), а вызов $Table->find('alias') вызовет $Behavior->findMethodName().
Рекомендуется (хотя и не обязательно), определять implementedFinders в свойстве config дочерних классов, чтобы не было необходимости использовать рефлексию для получения списка доступных методов. Смотрите примеры в базовых поведенииях.
Возвращает
массивimplementedMethods()source public
implementedMethods( )
implementedMethods
Предоставляет отображение «псевдоним» -> «имя метода», показывающее, какие методы реализует поведение. Пример:
[ 'method' => 'method', 'aliasedmethod' => 'somethingElse' ]
В приведенном выше примере вызов $Table->method() вызовет $Behavior->method(), а вызов $Table->aliasedmethod() вызовет $Behavior->somethingElse().
Рекомендуется (хотя и не обязательно), определять implementedFinders в свойстве config дочерних классов, чтобы не было необходимости использовать рефлексию для получения списка доступных методов. Смотрите примеры в базовых поведенииях.
Возвращает
массивverifyConfig()source public
verifyConfig( )
verifyConfig
Проверяет, что реализованные ключи содержат значения, указывающие на вызываемые объекты.
Выбрасывает
Cake\Core\Exception\Exceptionесли конфигурация некорректна
Методы, используемые из Cake\Core\InstanceConfigTrait
_configDelete()source protected
_configDelete( string $key )
Удаляет один ключ конфигурации.
Параметры
- строка
$key - Ключ для удаления.
Выбрасывает
Cake\Core\Exception\Exceptionесли попытка перезаписать существующую конфигурацию
_configRead()source protected
_configRead( string|null $key )
Читает значение ключа конфигурации.
Параметры
- строка|null
$key - Ключ для чтения.
Возвращает
смешанное_configWrite()source protected
_configWrite( string|array $key , mixed $value , boolean|string $merge false )
Записывает значение ключа конфигурации.
Параметры
- строка|массив
$key - Ключ для записи.
- смешанное
$value - Значение для записи.
- булево|строка
$mergeнеобязательно false Истинно, чтобы выполнить рекурсивное слияние, 'shallow' для простого слияния, ложно для перезаписи, по умолчанию ложно.
Выбрасывает
Cake\Core\Exception\Exceptionесли попытка перезаписать существующую конфигурацию
config()source public
config( string|array|null $key null , mixed|null $value null , boolean $merge true )
Получает/Устанавливает конфигурацию.
Использование
Чтение всей конфигурации:
$this->config();
Чтение определенного значения:
$this->config('key'); Чтение вложенного значения:
$this->config('some.nested.key'); Установка определенного значения:
$this->config('key', $value); Установка вложенного значения:
$this->config('some.nested.key', $value); Обновление нескольких настроек конфигурации одновременно:
$this->config(['one' => 'value', 'another' => 'value']);
Устарело
3.4.0 используйте setConfig()/getConfig() вместо этого.Параметры
- строка|массив|null
$keyнеобязательно null - Ключ для получения/установки или массив конфигураций.
- смешанное|null
$valueнеобязательно null - Значение для установки.
- булево
$mergeнеобязательно true - Выполнять ли рекурсивное слияние или перезапись существующей конфигурации, по умолчанию истина.
Возвращает
смешанноеЗначение конфигурации, которое читается, или сам объект при операциях записи.
Выбрасывает
Cake\Core\Exception\ExceptionПри попытке установить недопустимый ключ.
configShallow()source public
configShallow( string|array $key , mixed|null $value null )
Объединяет предоставленную конфигурацию с существующей. В отличие от config(), которая выполняет рекурсивное слияние для вложенных ключей, этот метод выполняет простое слияние.
Установка определенного значения:
$this->configShallow('key', $value); Установка вложенного значения:
$this->configShallow('some.nested.key', $value); Обновление нескольких настроек конфигурации одновременно:
$this->configShallow(['one' => 'value', 'another' => 'value']);
Параметры
- строка|массив
$key - Ключ для установки или полный массив конфигураций.
- смешанное|null
$valueнеобязательно null - Значение для установки.
Возвращает
$this
getConfig()source public
getConfig( string|null $key null , mixed $default null )
Возвращает конфигурацию.
Использование
Чтение всей конфигурации:
$this->getConfig();
Чтение определенного значения:
$this->getConfig('key'); Чтение вложенного значения:
$this->getConfig('some.nested.key'); Чтение со значением по умолчанию:
$this->getConfig('some-key', 'default-value'); Параметры
- строка|null
$keyнеобязательно null - Ключ для получения или null для всей конфигурации.
- смешанное
$defaultнеобязательно null - Возвращаемое значение, если ключ не существует.
Возвращает
смешанноеЗначение конфигурации, которое читается.
setConfig()source public
setConfig( string|array $key , mixed|null $value null , boolean $merge true )
Устанавливает конфигурацию.
Использование
Установка определенного значения:
$this->setConfig('key', $value); Установка вложенного значения:
$this->setConfig('some.nested.key', $value); Обновление нескольких настроек конфигурации одновременно:
$this->setConfig(['one' => 'value', 'another' => 'value']);
Параметры
- строка|массив
$key - Ключ для установки или полный массив конфигураций.
- смешанное|null
$valueнеобязательно null - Значение для установки.
- булево
$mergeнеобязательно true - Выполнять ли рекурсивное слияние или перезапись существующей конфигурации, по умолчанию истина.
Возвращает
$this
Выбрасывает
Cake\Core\Exception\ExceptionПри попытке установить недопустимый ключ.
Подробности свойств
$_defaultConfigsource
protected массив
Конфигурация по умолчанию
Эти значения объединяются с предоставленными пользователем настройками при использовании поведения.
[
'implementedFinders' => [
'path' => 'findPath',
'children' => 'findChildren',
'treeList' => 'findTreeList',
],
'implementedMethods' => [
'childCount' => 'childCount',
'moveUp' => 'moveUp',
'moveDown' => 'moveDown',
'recover' => 'recover',
'removeFromTree' => 'removeFromTree',
'getLevel' => 'getLevel',
'formatTreeList' => 'formatTreeList',
],
'parent' => 'parent_id',
'left' => 'lft',
'right' => 'rght',
'scope' => null,
'level' => null,
'recoverOrder' => null,
]
© 2005–2017 The Cake Software Foundation, Inc.
Licensed under the MIT License.
CakePHP is a registered trademark of Cake Software Foundation, Inc.
We are not endorsed by or affiliated with CakePHP.
https://api.cakephp.org/3.4/class-Cake.ORM.Behavior.TreeBehavior.html