Class TreeBehavior
Makes the table to which this is attached to behave like a nested set and provides methods for managing and retrieving information out of the derived hierarchical structure.
Tables attaching this behavior are required to have a column referencing the parent row, and two other numeric columns (lft and rght) where the implicit order will be cached.
For more information on what is a nested set and a how it works refer to https://www.sitepoint.com/hierarchical-data-database-2/
Property Summary
-
$_config protected
array<string, mixed>
Runtime config
-
$_configInitialized protected
bool
Whether the config property has already been configured with defaults
-
$_defaultConfig protected
array<string, mixed>
Default config
-
$_primaryKey protected
string
Cached copy of the first column in a table's primary key.
-
$_reflectionCache protected static
array<string, array>
Reflection method cache for behaviors.
-
$_table protected
Cake\ORM\Table
Table instance.
Method Summary
-
__construct() public
Constructor
-
_configDelete() protected
Deletes a single config key.
-
_configRead() protected
Reads a config key.
-
_configWrite() protected
Writes a config key.
-
_ensureFields() protected
Ensures that the provided entity contains non-empty values for the left and right fields
-
_getMax() protected
Returns the maximum index value in the table.
-
_getNode() protected
Returns a single node from the tree from its primary key
-
_getPrimaryKey() protected
Returns a single string value representing the primary key of the attached table
-
_moveDown() protected
Helper function used with the actual code for moveDown
-
_moveUp() protected
Helper function used with the actual code for moveUp
-
_recoverTree() protected
Recursive method used to recover a single level of the tree
-
_reflectionCache() protected
Gets the methods implemented by this behavior
-
_removeFromTree() protected
Helper function containing the actual code for removeFromTree
-
_resolveMethodAliases() protected
Removes aliased methods that would otherwise be duplicated by userland configuration.
-
_scope() protected
Alters the passed query so that it only returns scoped records as defined in the tree configuration.
-
_setAsRoot() protected
Updates the left and right column for the passed entity so it can be set as a new root in the tree. It also modifies the ordering in the rest of the tree so the structure remains valid
-
_setChildrenLevel() protected
Set level for descendants.
-
_setParent() protected
Sets the correct left and right values for the passed entity so it can be updated to a new parent. It also makes the hole in the tree so the node move can be done without corrupting the structure.
-
_sync() protected
Auxiliary function used to automatically alter the value of both the left and right columns by a certain amount that match the passed conditions
-
_unmarkInternalTree() protected
Helper method used to invert the sign of the left and right columns that are less than 0. They were set to negative values before so their absolute value wouldn't change while performing other tree transformations.
-
afterSave() public
After save listener.
-
beforeDelete() public
Also deletes the nodes in the subtree of the entity to be delete
-
beforeSave() public
Before save listener. Transparently manages setting the lft and rght fields if the parent field is included in the parameters to be saved.
-
childCount() public
Get the number of children nodes.
-
configShallow() public
Merge provided config with existing config. Unlike
config()
which does a recursive merge for nested keys, this method does a simple merge. -
findChildren() public
Get the children nodes of the current model
-
findPath() public
Custom finder method which can be used to return the list of nodes from the root to a specific node in the tree. This custom finder requires that the key 'for' is passed in the options containing the id of the node to get its path for.
-
findTreeList() public
Gets a representation of the elements in the tree as a flat list where the keys are the primary key for the table and the values are the display field for the table. Values are prefixed to visually indicate relative depth in the tree.
-
formatTreeList() public
Formats query as a flat list where the keys are the primary key for the table and the values are the display field for the table. Values are prefixed to visually indicate relative depth in the tree.
-
getConfig() public
Returns the config.
-
getConfigOrFail() public
Returns the config for this specific key.
-
getLevel() public
Returns the depth level of a node in the tree.
-
getTable() public deprecated
Get the table instance this behavior is bound to.
-
implementedEvents() public
Gets the Model callbacks this behavior is interested in.
-
implementedFinders() public
implementedFinders
-
implementedMethods() public
implementedMethods
-
initialize() public
Constructor hook method.
-
moveDown() public
Reorders the node without changing the parent.
-
moveUp() public
Reorders the node without changing its parent.
-
recover() public
Recovers the lft and right column values out of the hierarchy defined by the parent column.
-
removeFromTree() public
Removes the current node from the tree, by positioning it as a new root and re-parents all children up one level.
-
setConfig() public
Sets the config.
-
table() public
Get the table instance this behavior is bound to.
-
verifyConfig() public
verifyConfig
Method Detail
__construct() ¶ public
__construct(Cake\ORM\Table $table, array<string, mixed> $config = [])
Constructor
Merges config with the default and store in the config property
Parameters
-
Cake\ORM\Table
$table The table this behavior is attached to.
-
array<string, mixed>
$config optional The config for this behavior.
_configDelete() ¶ protected
_configDelete(string $key): void
Deletes a single config key.
Parameters
-
string
$key Key to delete.
Returns
void
Throws
Cake\Core\Exception\CakeException
if attempting to clobber existing config
_configRead() ¶ protected
_configRead(string|null $key): mixed
Reads a config key.
Parameters
-
string|null
$key Key to read.
Returns
mixed
_configWrite() ¶ protected
_configWrite(array<string, mixed>|string $key, mixed $value, string|bool $merge = false): void
Writes a config key.
Parameters
-
array<string, mixed>|string
$key Key to write to.
-
mixed
$value Value to write.
-
string|bool
$merge optional True to merge recursively, 'shallow' for simple merge, false to overwrite, defaults to false.
Returns
void
Throws
Cake\Core\Exception\CakeException
if attempting to clobber existing config
_ensureFields() ¶ protected
_ensureFields(Cake\Datasource\EntityInterface $entity): void
Ensures that the provided entity contains non-empty values for the left and right fields
Parameters
-
Cake\Datasource\EntityInterface
$entity The entity to ensure fields for
Returns
void
_getNode() ¶ protected
_getNode(mixed $id): Cake\Datasource\EntityInterface
Returns a single node from the tree from its primary key
Parameters
-
mixed
$id Record id.
Returns
Cake\Datasource\EntityInterface
Throws
Cake\Datasource\Exception\RecordNotFoundException
When node was not found
_getPrimaryKey() ¶ protected
_getPrimaryKey(): string
Returns a single string value representing the primary key of the attached table
Returns
string
_moveDown() ¶ protected
_moveDown(Cake\Datasource\EntityInterface $node, int|true $number): Cake\Datasource\EntityInterface
Helper function used with the actual code for moveDown
Parameters
-
Cake\Datasource\EntityInterface
$node The node to move
-
int|true
$number How many places to move the node, or true to move to last position
Returns
Cake\Datasource\EntityInterface
Throws
Cake\Datasource\Exception\RecordNotFoundException
When node was not found
_moveUp() ¶ protected
_moveUp(Cake\Datasource\EntityInterface $node, int|true $number): Cake\Datasource\EntityInterface
Helper function used with the actual code for moveUp
Parameters
-
Cake\Datasource\EntityInterface
$node The node to move
-
int|true
$number How many places to move the node, or true to move to first position
Returns
Cake\Datasource\EntityInterface
Throws
Cake\Datasource\Exception\RecordNotFoundException
When node was not found
_recoverTree() ¶ protected
_recoverTree(int $lftRght = 1, mixed $parentId = null, int $level = 0): int
Recursive method used to recover a single level of the tree
Parameters
-
int
$lftRght optional The starting lft/rght value
-
mixed
$parentId optional the parent id of the level to be recovered
-
int
$level optional Node level
Returns
int
_reflectionCache() ¶ protected
_reflectionCache(): array
Gets the methods implemented by this behavior
Uses the implementedEvents() method to exclude callback methods.
Methods starting with _
will be ignored, as will methods
declared on Cake\ORM\Behavior
Returns
array
Throws
ReflectionException
_removeFromTree() ¶ protected
_removeFromTree(Cake\Datasource\EntityInterface $node): Cake\Datasource\EntityInterface|false
Helper function containing the actual code for removeFromTree
Parameters
-
Cake\Datasource\EntityInterface
$node The node to remove from the tree
Returns
Cake\Datasource\EntityInterface|false
_resolveMethodAliases() ¶ protected
_resolveMethodAliases(string $key, array<string, mixed> $defaults, array<string, mixed> $config): array
Removes aliased methods that would otherwise be duplicated by userland configuration.
Parameters
-
string
$key The key to filter.
-
array<string, mixed>
$defaults The default method mappings.
-
array<string, mixed>
$config The customized method mappings.
Returns
array
_scope() ¶ protected
_scope(Cake\ORM\Query $query): Cake\ORM\Query
Alters the passed query so that it only returns scoped records as defined in the tree configuration.
Parameters
-
Cake\ORM\Query
$query the Query to modify
Returns
Cake\ORM\Query
_setAsRoot() ¶ protected
_setAsRoot(Cake\Datasource\EntityInterface $entity): void
Updates the left and right column for the passed entity so it can be set as a new root in the tree. It also modifies the ordering in the rest of the tree so the structure remains valid
Parameters
-
Cake\Datasource\EntityInterface
$entity The entity to set as a new root
Returns
void
_setChildrenLevel() ¶ protected
_setChildrenLevel(Cake\Datasource\EntityInterface $entity): void
Set level for descendants.
Parameters
-
Cake\Datasource\EntityInterface
$entity The entity whose descendants need to be updated.
Returns
void
_setParent() ¶ protected
_setParent(Cake\Datasource\EntityInterface $entity, mixed $parent): void
Sets the correct left and right values for the passed entity so it can be updated to a new parent. It also makes the hole in the tree so the node move can be done without corrupting the structure.
Parameters
-
Cake\Datasource\EntityInterface
$entity The entity to re-parent
-
mixed
$parent the id of the parent to set
Returns
void
Throws
RuntimeException
if the parent to set to the entity is not valid
_sync() ¶ protected
_sync(int $shift, string $dir, string $conditions, bool $mark = false): void
Auxiliary function used to automatically alter the value of both the left and right columns by a certain amount that match the passed conditions
Parameters
-
int
$shift the value to use for operating the left and right columns
-
string
$dir The operator to use for shifting the value (+/-)
-
string
$conditions a SQL snipped to be used for comparing left or right against it.
-
bool
$mark optional whether to mark the updated values so that they can not be modified by future calls to this function.
Returns
void
_unmarkInternalTree() ¶ protected
_unmarkInternalTree(): void
Helper method used to invert the sign of the left and right columns that are less than 0. They were set to negative values before so their absolute value wouldn't change while performing other tree transformations.
Returns
void
afterSave() ¶ public
afterSave(Cake\Event\EventInterface $event, Cake\Datasource\EntityInterface $entity): void
After save listener.
Manages updating level of descendants of currently saved entity.
Parameters
-
Cake\Event\EventInterface
$event The afterSave event that was fired
-
Cake\Datasource\EntityInterface
$entity the entity that is going to be saved
Returns
void
beforeDelete() ¶ public
beforeDelete(Cake\Event\EventInterface $event, Cake\Datasource\EntityInterface $entity): void
Also deletes the nodes in the subtree of the entity to be delete
Parameters
-
Cake\Event\EventInterface
$event The beforeDelete event that was fired
-
Cake\Datasource\EntityInterface
$entity The entity that is going to be saved
Returns
void
beforeSave() ¶ public
beforeSave(Cake\Event\EventInterface $event, Cake\Datasource\EntityInterface $entity): void
Before save listener. Transparently manages setting the lft and rght fields if the parent field is included in the parameters to be saved.
Parameters
-
Cake\Event\EventInterface
$event The beforeSave event that was fired
-
Cake\Datasource\EntityInterface
$entity the entity that is going to be saved
Returns
void
Throws
RuntimeException
if the parent to set for the node is invalid
childCount() ¶ public
childCount(Cake\Datasource\EntityInterface $node, bool $direct = false): int
Get the number of children nodes.
Parameters
-
Cake\Datasource\EntityInterface
$node The entity to count children for
-
bool
$direct optional whether to count all nodes in the subtree or just direct children
Returns
int
configShallow() ¶ public
configShallow(array<string, mixed>|string $key, mixed|null $value = null): $this
Merge provided config with existing config. Unlike config()
which does
a recursive merge for nested keys, this method does a simple merge.
Setting a specific value:
$this->configShallow('key', $value);
Setting a nested value:
$this->configShallow('some.nested.key', $value);
Updating multiple config settings at the same time:
$this->configShallow(['one' => 'value', 'another' => 'value']);
Parameters
-
array<string, mixed>|string
$key The key to set, or a complete array of configs.
-
mixed|null
$value optional The value to set.
Returns
$this
findChildren() ¶ public
findChildren(Cake\ORM\Query $query, array<string, mixed> $options): Cake\ORM\Query
Get the children nodes of the current model
Available options are:
- for: The id of the record to read.
- direct: Boolean, whether to return only the direct (true), or all (false) children, defaults to false (all children).
If the direct option is set to true, only the direct children are returned (based upon the parent_id field)
Parameters
-
Cake\ORM\Query
$query Query.
-
array<string, mixed>
$options Array of options as described above
Returns
Cake\ORM\Query
Throws
InvalidArgumentException
When the 'for' key is not passed in $options
findPath() ¶ public
findPath(Cake\ORM\Query $query, array<string, mixed> $options): Cake\ORM\Query
Custom finder method which can be used to return the list of nodes from the root to a specific node in the tree. This custom finder requires that the key 'for' is passed in the options containing the id of the node to get its path for.
Parameters
-
Cake\ORM\Query
$query The constructed query to modify
-
array<string, mixed>
$options the list of options for the query
Returns
Cake\ORM\Query
Throws
InvalidArgumentException
If the 'for' key is missing in options
findTreeList() ¶ public
findTreeList(Cake\ORM\Query $query, array<string, mixed> $options): Cake\ORM\Query
Gets a representation of the elements in the tree as a flat list where the keys are the primary key for the table and the values are the display field for the table. Values are prefixed to visually indicate relative depth in the tree.
Options
- keyPath: A dot separated path to fetch the field to use for the array key, or a closure to return the key out of the provided row.
- valuePath: A dot separated path to fetch the field to use for the array value, or a closure to return the value out of the provided row.
- spacer: A string to be used as prefix for denoting the depth in the tree for each item
Parameters
-
Cake\ORM\Query
$query Query.
-
array<string, mixed>
$options Array of options as described above.
Returns
Cake\ORM\Query
formatTreeList() ¶ public
formatTreeList(Cake\ORM\Query $query, array<string, mixed> $options = []): Cake\ORM\Query
Formats query as a flat list where the keys are the primary key for the table and the values are the display field for the table. Values are prefixed to visually indicate relative depth in the tree.
Options
- keyPath: A dot separated path to the field that will be the result array key, or a closure to return the key from the provided row.
- valuePath: A dot separated path to the field that is the array's value, or a closure to return the value from the provided row.
- spacer: A string to be used as prefix for denoting the depth in the tree for each item.
Parameters
-
Cake\ORM\Query
$query The query object to format.
-
array<string, mixed>
$options optional Array of options as described above.
Returns
Cake\ORM\Query
getConfig() ¶ public
getConfig(string|null $key = null, mixed $default = null): mixed
Returns the config.
Usage
Reading the whole config:
$this->getConfig();
Reading a specific value:
$this->getConfig('key');
Reading a nested value:
$this->getConfig('some.nested.key');
Reading with default value:
$this->getConfig('some-key', 'default-value');
Parameters
-
string|null
$key optional The key to get or null for the whole config.
-
mixed
$default optional The return value when the key does not exist.
Returns
mixed
getConfigOrFail() ¶ public
getConfigOrFail(string $key): mixed
Returns the config for this specific key.
The config value for this key must exist, it can never be null.
Parameters
-
string
$key The key to get.
Returns
mixed
Throws
InvalidArgumentException
getLevel() ¶ public
getLevel(Cake\Datasource\EntityInterface|string|int $entity): int|false
Returns the depth level of a node in the tree.
Parameters
-
Cake\Datasource\EntityInterface|string|int
$entity The entity or primary key get the level of.
Returns
int|false
getTable() ¶ public
getTable(): Cake\ORM\Table
Get the table instance this behavior is bound to.
Returns
Cake\ORM\Table
implementedEvents() ¶ public
implementedEvents(): array<string, mixed>
Gets the Model callbacks this behavior is interested in.
By defining one of the callback methods a behavior is assumed to be interested in the related event.
Override this method if you need to add non-conventional event listeners. Or if you want your behavior to listen to non-standard events.
Returns
array<string, mixed>
implementedFinders() ¶ public
implementedFinders(): array
implementedFinders
Provides an alias->methodname map of which finders a behavior implements. Example:
[
'this' => 'findThis',
'alias' => 'findMethodName'
]
With the above example, a call to $table->find('this')
will call $behavior->findThis()
and a call to $table->find('alias')
will call $behavior->findMethodName()
It is recommended, though not required, to define implementedFinders in the config property of child classes such that it is not necessary to use reflections to derive the available method list. See core behaviors for examples
Returns
array
Throws
ReflectionException
implementedMethods() ¶ public
implementedMethods(): array
implementedMethods
Provides an alias->methodname map of which methods a behavior implements. Example:
[
'method' => 'method',
'aliasedMethod' => 'somethingElse'
]
With the above example, a call to $table->method()
will call $behavior->method()
and a call to $table->aliasedMethod()
will call $behavior->somethingElse()
It is recommended, though not required, to define implementedFinders in the config property of child classes such that it is not necessary to use reflections to derive the available method list. See core behaviors for examples
Returns
array
Throws
ReflectionException
initialize() ¶ public
initialize(array<string, mixed> $config): void
Constructor hook method.
Implement this method to avoid having to overwrite the constructor and call parent.
Parameters
-
array<string, mixed>
$config
Returns
void
moveDown() ¶ public
moveDown(Cake\Datasource\EntityInterface $node, int|true $number = 1): Cake\Datasource\EntityInterface|false
Reorders the node without changing the parent.
If the node is the last child, or is a top level node with no subsequent node this method will return the same node without any changes
Parameters
-
Cake\Datasource\EntityInterface
$node The node to move
-
int|true
$number optional How many places to move the node or true to move to last position
Returns
Cake\Datasource\EntityInterface|false
Throws
Cake\Datasource\Exception\RecordNotFoundException
When node was not found
moveUp() ¶ public
moveUp(Cake\Datasource\EntityInterface $node, int|true $number = 1): Cake\Datasource\EntityInterface|false
Reorders the node without changing its parent.
If the node is the first child, or is a top level node with no previous node this method will return the same node without any changes
Parameters
-
Cake\Datasource\EntityInterface
$node The node to move
-
int|true
$number optional How many places to move the node, or true to move to first position
Returns
Cake\Datasource\EntityInterface|false
Throws
Cake\Datasource\Exception\RecordNotFoundException
When node was not found
recover() ¶ public
recover(): void
Recovers the lft and right column values out of the hierarchy defined by the parent column.
Returns
void
removeFromTree() ¶ public
removeFromTree(Cake\Datasource\EntityInterface $node): Cake\Datasource\EntityInterface|false
Removes the current node from the tree, by positioning it as a new root and re-parents all children up one level.
Note that the node will not be deleted just moved away from its current position without moving its children with it.
Parameters
-
Cake\Datasource\EntityInterface
$node The node to remove from the tree
Returns
Cake\Datasource\EntityInterface|false
setConfig() ¶ public
setConfig(array<string, mixed>|string $key, mixed|null $value = null, bool $merge = true): $this
Sets the config.
Usage
Setting a specific value:
$this->setConfig('key', $value);
Setting a nested value:
$this->setConfig('some.nested.key', $value);
Updating multiple config settings at the same time:
$this->setConfig(['one' => 'value', 'another' => 'value']);
Parameters
-
array<string, mixed>|string
$key The key to set, or a complete array of configs.
-
mixed|null
$value optional The value to set.
-
bool
$merge optional Whether to recursively merge or overwrite existing config, defaults to true.
Returns
$this
Throws
Cake\Core\Exception\CakeException
When trying to set a key that is invalid.
table() ¶ public
table(): Cake\ORM\Table
Get the table instance this behavior is bound to.
Returns
Cake\ORM\Table
verifyConfig() ¶ public
verifyConfig(): void
verifyConfig
Checks that implemented keys contain values pointing at callable.
Returns
void
Throws
Cake\Core\Exception\CakeException
if config are invalid
Property Detail
$_configInitialized ¶ protected
Whether the config property has already been configured with defaults
Type
bool
$_defaultConfig ¶ protected
Default config
These are merged with user-provided configuration when the behavior is used.
Type
array<string, mixed>
$_reflectionCache ¶ protected static
Reflection method cache for behaviors.
Stores the reflected method + finder methods per class. This prevents reflecting the same class multiple times in a single process.
Type
array<string, array>