1

How can I turn the first array in to the second one? The goal is to create an array that shows the hierarchy, based on location_id and parent_id. Each location_name should be in an array of which the key is its parent_id.

Ignore the values I gave to location_name. No value for parent_id == NULL, these are the top level items.

First array:

    Array
    (
        [0] => stdClass Object
            (
                [location_id] => 1
                [location_name] => Town 1
                [parent_id] => 
            )

        [1] => stdClass Object
            (
                [location_id] => 2
                [location_name] => Town 1.1
                [parent_id] => 
            )

        [2] => stdClass Object
            (
                [location_id] => 3
                [location_name] => Town 1.2
                [parent_id] => 1
            )

        [3] => stdClass Object
            (
                [location_id] => 4
                [location_name] => Town 1.3
                [parent_id] => 1
            )

        [4] => stdClass Object
            (
                [location_id] => 5
                [location_name] => town 1.1.1
                [parent_id] => 2
            )

        [5] => stdClass Object
            (
                [location_id] => 6
                [location_name] => Town 1.1.2
                [parent_id] => 3
            )
);

Resulting array should be:

Array(
        'Town 1' = array(
            'town 1.2',
            'town 1.3' = array(
                 'town 1.1.2'
             )
        ),
        'Town 2' = array(
             'town 1.1.1'
        )
    );

EDIT: working solution based on Rijk's answer

function _order_locs($parent, $array)
    {
        $return = array();
        foreach ( $array as $town )
        {
            if ( $town->parent_id == $parent )
            {
                $set = $this->_order_locs( $town->location_id, $array );               
                if( $this->_menu_is_parent($town->location_id, $array) ) $return[$town->location_name] = $set;
                else $return[] = $town->location_name;            
            }
        }

        return $return;
    }

    function _menu_is_parent($id, $array)
    {
        foreach( $array as $a )
        {
            if( $a->parent_id == $id ) return TRUE;
        }
    }
0

2 Answers 2

3

You have to loop through it, using a recursive function (one that calls itself):

function getChilds( $parent, $array ) {
    $return = array();
    foreach ( $array as $town ) {
        if ( $town['location_id'] == $parent ) {
            $return[] = array(
                'name' => $town['location_name'],
                'childs' => getChilds( $town['location_id'], $array )
            );
        }
    }
    return $return;
}

$towns_tree = getChilds( 0, $towns );

Might not work right off the bat, but that gives you a nice oppurtunity to play with the code and get familiar with this concept ;)

Sign up to request clarification or add additional context in comments.

Comments

0

Here is some code that will more or less do what you need. You will have to tweak it to your liking.

<?php

Class Node {
   public $id;
   public $parent_id;
   public $value;
   public $children;
   public $depth;

   function __construct($id, $parent_id, $value) {
      $this->id = $id;
      $this->parent_id = $parent_id;
      $this->value = $value;
          $this->children = array();
      $this->depth = 0;
   }

   function add_child(Node $new_child) {
      if ($new_child->parent_id == $this->id) {
         $this->children[$new_child->id] = $new_child;
         $this->children[$new_child->id]->depth = $this->depth + 1;
      } else {
         foreach ($this->children as $child) {
            $child->add_child($new_child);
         }
      }
   }

   function to_array() {
      if (count($this->children) > 0) {
         $arr = array();
         foreach ($this->children as $child) {
            array_push($arr, $child->to_array());
         }
         return array($this->value => $arr);
      } else {
         return $this->value;
      }
   }

   function str() {
      echo str_repeat(" ", $this->depth) . $this->value . "\n";
      foreach ($this->children as $child) {
         $child->str();
      }
   }
}

?>

Here is some sample code to test it with:

<?php

$arr = Array(
   array('location_id' => 1,
         'location_name' => 'Town 1',
         'parent_id' => 0),

   array('location_id' => 2,
         'location_name' => 'Town 1.1',
         'parent_id' => 0),

   array('location_id' => 3,
         'location_name' => 'Town 1.2',
         'parent_id' => 1),

   array('location_id' => 4,
         'location_name' => 'Town 1.3',
         'parent_id' => 1),

   array('location_id' => 5,
         'location_name' => 'Town 1.1.1',
         'parent_id' => 2),

       array('location_id' => 6,
         'location_name' => 'Town 1.1.2',
         'parent_id' => 3)
);

$root = new Node(0, 0, 'root');
foreach ($arr as $item) {
   $node = new Node($item['location_id'],
                    $item['parent_id'],
                    $item['location_name']);
   $root->add_child($node);
}
$tree = $root->to_array();
$tree = $tree['root'];
var_dump($tree);

?>

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.