2

I'm strugling with building an array out of a product category array. This array is a tree array with parents and children. No I selecting one of the children, and I want to build the permalink towards this child.

I'm almost there, but somewhere I'm making a mistake and I can't figure it out.

So lets say I have this category array.

$cat = [
    0 => [
        "id" => "32",
        "shop_id" => "19",
        "parent_id" => "0",
        "name" => "T-shirts",
        "permalink" => "t-shirts",
        "image" => "category/image.jpg",
        "description" => "",
        "order" => "0",
        "children" => [
            0 => [
                "id" => "33",
                "shop_id" => "19",
                "parent_id" => "32",
                "name" => "Dames",
                "permalink" => "t-shirts/dames",
                "image" => "category/image.jpg",
                "description" => "",
                "order" => "0",
                "children" => [
                    0 => [
                        "id" => "38",
                        "shop_id" => "19",
                        "parent_id" => "33",
                        "name" => "V-hals",
                        "permalink" => "t-shirts/dames/v-hals",
                        "image" => "category/image.jpg",
                        "description" => "",
                        "order" => "0",
                        "children" => [
                            0 => [
                                "id" => "40",
                                "shop_id" => "19",
                                "parent_id" => "38",
                                "name" => "Rood",
                                "permalink" => "t-shirts/dames/v-hals/rood",
                                "image" => "",
                                "description" => "",
                                "order" => "0",
                                "children" => [
                                    0 => [
                                        "id" => "47",
                                        "shop_id" => "19",
                                        "parent_id" => "40",
                                        "name" => "Lange mouw",
                                        "permalink" => "t-shirts/dames/v-hals/rood/lange-mouw",
                                        "image" => "",
                                        "description" => "",
                                        "order" => "0",
                                        "children" => null,
                                    ]
                                ]
                            ]
                        ]
                    ]
                ]
            ]
        ]
    ]
];

Now I'm at category_id 38 and I want to build the breadcrumb. To accomplish that, I need the name of each category, and the permalink.

To accomplish that, I have flattend this array so they are all at the same level. At that point I'm using the following function:

function build_breadcrumb_from_category($categories, $pid)
{
    $return = [];
    foreach ($categories as $category) {
        if ($pid == $category['id']) {

            $return[] = [$category['name'], $category['permalink']];

            if ($category['parent_id'] > 0) {
                # Page has parents
                $return[] = build_breadcrumb_from_category($categories, $category['parent_id']);

            }

        }
    }
    return array_reverse($return);
}

But that gives me a kind of "tree" array again.

$breadcrumb = build_breadcrumb_from_category($flat_categories, 38);
$breadcrumb = [
    0 => [
        0 => [
            0 => [
                0 => [
                    0 => [
                        0 => "T-shirts",
                        1 => "t-shirts",
                    ],
                ],
                1 => [
                    0 => "Dames",
                    1 => "t-shirts/dames",
                ],
            ],
            1 => [
                0 => "V-hals",
                1 => "t-shirts/dames/v-hals",
            ]
        ],
        1 => [
            0 => "Rood",
            1 => "t-shirts/dames/v-hals/rood",
        ],
    ],
    1 => [
        0 => "Lange mouw",
        1 => "t-shirts/dames/v-hals/rood/lange-mouw",
    ],
];

I don't understand how I can get this array flat. How can I get a nice array, just one level deep where I can do a foreach.

Desired output

   $breadcrumbs = [
       [       
            0 => "T-shirts",
            1 => "t-shirts",
       ],
       [       
            0 => "Dames",
            1 => "t-shirts/dames",
       ],
       [       
            0 => "V-hals",
            1 => "t-shirts/dames/v-hals",
       ],
    ]
3
  • what's the desired output look like? Commented Dec 5, 2016 at 20:27
  • @Dagon, the $output array, but flat, all on the same level. Commented Dec 5, 2016 at 20:28
  • post it as an array in your question Commented Dec 5, 2016 at 20:28

2 Answers 2

5

You could optimise this by indexing flattened array - too many search loops now (post your flattening function if you want better solution). The function you have doesn't need big changes though. You should build your parent structure first, push current position and then return it to higher scope (as its parent structure):

function build_breadcrumb_from_category($categories, $pid)
{
    $result = [];
    foreach ($categories as $category) {
        if ($pid == $category['id']) {
            if ($category['parent_id'] > 0) {
                # Page has parents
                $result = build_breadcrumb_from_category($categories, $category['parent_id']);
            }

            $result[] = [$category['name'], $category['permalink']];
        }
    }
    return $result;
}

Here's the solution with indexed category list - first function flattens the tree, second one uses its id indexes to build breadcrub path:

function category_index($category_tree)
{
    $result = [];
    foreach($category_tree as $category) {
        if (!empty($category['children'])) {
            $result = $result + category_index($category['children']);
        }
        unset($category['children']);
        $result[$category['id']] = $category;
    }
    return $result;
}

function category_breadcrumb($category_index, $pid)
{
    if (empty($category_index[$pid])) { return []; }

    $category = $category_index[$pid];
    $result   = ($category['parent_id']) ? category_breadcrumb($category_index, $category['parent_id']) : [];
    $result[] = [$category['name'], $category['permalink']];

    return $result;
}
Sign up to request clarification or add additional context in comments.

2 Comments

Your function build_breadcrumb_from_category does the job! Awesome! I also tested with calling the function again (if it still has a parent) to put the result not in a array. But that allways gave me the latest result. But I also had $result[] = above the if
@Timo002 If you intend to use refactored original function you might add break; inside if or just return from there - no need to search further after id was found.
1

My solution

function build_breadcrumb_from_category($categories, $pid)
{
    $result = [];
    foreach ($categories as $category)
    {
        if ($pid == $category['id'])
        {
            return [[$category['name'], $category['permalink']]];
        }

        $result = build_breadcrumb_from_category($category['children'], $pid);

        if (!empty($result))
        {   
            $result[] = [$category['name'], $category['permalink']];
            return $result;
        }       
    }    
}

Comments

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.