3

I need to sort an array of objects hierarchically. The data looks like this:

array (size=54)
  0 => 
    object(stdClass)[786]
      public 'term_id' => string '1' (length=3)
      public 'name' => string 'Boots' (length=25)
      public 'parent' => string '0' (length=3)
  1 => 
    object(stdClass)[785]
      public 'term_id' => string '2' (length=3)
      public 'name' => string 'Dresses' (length=25)
      public 'parent' => string '1' (length=3)
  2 => 
    object(stdClass)[786]
      public 'term_id' => string '3' (length=3)
      public 'name' => string 'Scarves' (length=25)
      public 'parent' => string '2' (length=3)
  3 => 
    object(stdClass)[785]
      public 'term_id' => string '4' (length=3)
      public 'name' => string 'Gloves' (length=25)
      public 'parent' => string '1' (length=3)

I want to create a multidimensional array that would show this hierarchy of "parent and children". The parent property of each object refers to the term_id of another object.

The result would look something like this:

array (size=54)
  0 => 
    object(stdClass)[786]
      public 'term_id' => string '1' (length=3)
      public 'name' => string 'Boots' (length=25)
      public 'parent' => string '0' (length=3)
      public 'children' => array (size=2)
            0 => 
                object(stdClass)[785]
                  public 'term_id' => string '2' (length=3)
                  public 'name' => string 'Dresses' (length=25)
                  public 'parent' => string '1' (length=3)
                  public 'children' => (size=1)
                      0 => 
                        object(stdClass)[786]
                          public 'term_id' => string '3' (length=3)
                          public 'name' => string 'Scarves' (length=25)
                          public 'parent' => string '2' (length=3)
            1 =>
                object(stdClass)[785]
                  public 'term_id' => string '4' (length=3)
                  public 'name' => string 'Gloves' (length=25)
                  public 'parent' => string '1' (length=3)      

So far I have come up with this code:

$sortedCategories = array();
foreach($shopCategories as $shopCategory) {       
    $tmp = $shopCategory;
    foreach($shopCategories as $category) {
        if ($tmp->term_id == $category->parent) {
            $tmp->children[] = $category;
            $sortedCategories[] = $tmp;
        } 
    }
}

,but I cannot get it work with the multi-level hierarchy.

How can I sort the data to achieve the desired result?

1 Answer 1

4

I would use a recursive function. It isn't really sorting that you are doing. You are building a tree structure. Assume your original objects are in an array called $a and you want the new tree to be called $b. What this function does is add everyone who is a child of the current parent you are working on. Every time it adds a child, it also calls itself to add that object's children. Hence, the recursion. You start with a parent of 0, which I assume means "no parent".

$b = build_tree($a);

function build_tree(&$a, $parent=0)
{
    $tmp_array = array();
    foreach($a as $obj)
    {
        if($obj->parent == $parent)
        {
            // The next line adds all children to this object
            $obj->children = build_tree($a, $obj->term_id);
            $tmp_array[] = $obj
        }
    }
    // You *could* sort the temp array here if you wanted.
    return $tmp_array;
}
Sign up to request clarification or add additional context in comments.

4 Comments

Works perfectly. There is only one question I have. Why do you pass $a by reference to the build_tree function ? Is this necessary? Thank you a lot!
I'm not going to alter $a in any way, so there is not reason to copy the entire array. That would just waste time and memory.
This is a very reasonable point. I must say the script that you proposed in your reply looks so neat and straightforward, but I find it difficult to rewalk its steps in my head. I definitely need practice..
The walk is rather simple: Start with root (null) node. Add all the children to the root. When you add a child, right before you add it, add all children to that node. So, when you are adding those children, right before you add then, add all their children. Another note: I use recursion here because the recursion takes place in the middle of the function. If you ever write a recursive function and the recursion is at the end, you did it wrong.

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.