2

I'm trying to create dynamic breadcrumbs from an array. So I can add to the array and not have to manually update the breadcrumbs.

Okay, here's a snippet of my array: (It won't go much deeper)

$menu = array(
    'Dashboard' => array(
        'Projects' => array(
            'Project 1' => array(
                'Project settings' => 'projects/project_1/settings',
                'Issue Tracker' => 'projects/project_1/issue_tracker',
                'Customize page' => 'projects/project_1',
                'Manage files' => 'projects/project_1/files',
            ),
            'Project 2' => array(
                'Project settings' => 'projects/project_2/settings',
                'Issue Tracker' => 'projects/project_2/issue_tracker',
                'Customize page' => 'projects/project_2',
                'Manage files' => 'projects/project_2/files',
            ),
        ),
        'Logout' => '#',
    )
);

I would like to be able to return all the parents of any key in a way that I can iterate through later. For instance, for 'Project settings':

'Dashboard','Projects','Project 1'.
3
  • 1
    All I can say right now is that this has been asked and answered before on the site. Let me look if I can pull it up from the archives for you. Commented Dec 24, 2012 at 11:53
  • Wouldn't Getting data from one way array in reverse order suit your needs? Commented Dec 24, 2012 at 11:54
  • Had a quick look. It's kind there, but isn't that just reversing an array? How would I isolate the parents of the key I'm looking for? Commented Dec 24, 2012 at 12:30

1 Answer 1

3

In your example there are actually two paths possible:

Key 'Project settings' found: 'Projects' -> 'Project 1'
Key 'Project settings' found: 'Projects' -> 'Project 2'

You can easily solve this with a recursive iterator (See RecursiveIteratorIterator it offers all you need). I chose it because it allows you to easier search and obtain the parent levels keys:

$search = 'Project settings';
$it     = new ParentKeysIterator($menu);
foreach ($it as $key) {
    if ($key !== $search) continue;
    printf("Key '%s' found: '%s'\n", $key, implode("' -> '", $it->key()));
}

And the ParentKeysIterator:

class ParentKeysIterator extends RecursiveIteratorIterator
{
    public function __construct(array $array) {
        parent::__construct(new  RecursiveArrayIterator($array));
    }

    public function current() {
        return parent::key();
    }

    public function key() {
        return $this->getParentKeys();
    }


    public function getParentKeys() {
        $keys = [];
        for ($depth = $this->getDepth() - 1; $depth; $depth--) {
            array_unshift($keys, $this->getSubIterator($depth)->key());
        }
        return $keys;
    }
}
Sign up to request clarification or add additional context in comments.

6 Comments

Wow, thanks. That's looks pretty good. Are you sure it's not possible without an external class? I'm not a fan of relying on entire classes just for one or two functions - makes it seem bloated...
Those classes are built-in in PHP. And the third class you write your own so is not external. If you want that per some functions, check the other question I've linked. And then you need to code the whole logic that is already in RecursiveIteratorIterator your own which would be re-inventing the wheel, something you normally don't want to do.
I made one adjustment: the for loop should be for ($depth = $this->getDepth(); $depth>=0; $depth--) so that it can properly return a key found at the top-most level ("Dashboard", in this example).
@N13: For the topmost key you do not need the loop, it is always: $this->getSubIterator($depth = 0)->key(); (variable in there only to name the value).
@hakre: In this example, yes. It didn't work for my data structure, though, so I wanted to share a broader solution. While you're here, do you know of a way to use the returned $keys array to retrieve the values from $menu?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.