CakePHP Tree Find By Path
Wrote these little functions to help with finding tree nodes by specifying a path of values. For example if we had a tree of categories with similar names like TVs->Color and Movies->Color, we can’t find by the category name since its not unique, but we can search by pathing like tvs/color or movies/color. So to this end is this model code:
function findPath($paths, $fieldName) {
$root = $this->find('threaded');
return $this->findPathHelper($root, $paths, $fieldName);
}
function findPathHelper($node, $paths, $fieldName) {
// search for paths from the beginning of the list
$path = array_shift($paths);
$newNode = false;
// looking for the current path in the specified field
foreach ($node as $nodeNode) {
if ($nodeNode[$this->name][$fieldName] == $path) {
$newNode = $nodeNode;
break;
}
}
if (empty($paths) || $newNode === false) {
// done processing the paths, or cannot find a matching node
return $newNode;
} else {
// not done, find based on the found node's children
return $this->findPathHelper($newNode['children'], $paths, $fieldName);
}
}
And we can use it from our controller like:
$category = $this->Category->findPath(array('tv', 'color'), 'name');
Probably not the most efficient code, but it sure is elegant. It also will probably break if you have two rows on the same level with the same name, but that would be pointless anyway.
September 5th, 2008 at 4:50 am
i believe,
your solution…
was already implemented in the cakephp ACL
( not Auth component )
its just, they were for ACL
( but still can use for others i guess )
( i meet the same problem, but the problem was in ACL )
( where User->Ali and Admin->Ali, not unique problem )
see the ACL API
you will see the id( ), getparent( ), getpath( ) and getchild( )
then modify the id( $alias )
into id( $alias, $smelly )
where $smelly is the array of path
base on your
findPath(array(‘tv’, ‘color’), ‘name’)
i guess it will be about
alias( ‘ tv ‘, array( ‘ color ‘ ) );
it will return the integer which is ‘foreign_key’
what bout the ‘name’ ?
well in the ACL its fixed as ‘foreign_key’
so no need to put a name field for it
finally,
make something like
getpath( alias( ‘ tv ‘, array( ‘ color ‘ ) ) );
will do the trick i guess
p/s:
this is just a suggestion
i never implement or try those code above yet
but i do believe it can be done…
May 23rd, 2010 at 9:21 am
Hi,I find that your weblog is extremely informative and helpful and we were curious if there can be a possibility of getting More web content like this on your web site. If you willing to aid us out, we would be willing to compensate you… Best wishes, Mauricio Hafford