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.

This entry was posted on Thursday, July 24th, 2008 at 1:11 pm and is filed under CakePHP. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

2 Responses to “CakePHP Tree Find By Path”

  1. asipo Says:

    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…

  2. Mauricio Hafford Says:

    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

Leave a Reply