0

Possible Duplicate:
Converting an array from one to multi-dimensional based on parent ID values

I'm trying to arrange a bunch of categories into their hierarchies. I have an SQL table for the categories that only stores their cid (category id), title, parent (parent id).

It's not done yet but basically I'm stuck at the point where if a category has a parent then I'm trying to grab it by reference (see line **NOT WORKING**). I want to update the $return array to reflect the change

//  returns categories in their correct heierarchy
function organize_categories( $array ) {
  $return = array();

  //  instead of retyping the same thing over and over again
  function create_record( $data ) {
    return array(
          'title' => $data->title,
          'children' => array()
    );
  }

  //  go over each row
  foreach( $array as $id => $cat ) {

    //  if it doesn't have a parent (AKA 0)
    if( !$cat->parent ) {

      $return[ $id ] = create_record( $cat );

    } else {

      //  get reference of parent **NOT WORKING**
      $parent =& search_category( $cat->parent , $return );

      if( $parent )
        $parent[ 'children' ][ $id ] = create_record( $cat );
      else
        $return[ $id ] = create_record( $cat );

    }
  }

  return $return;
}

function search_category( $pid , $array ) {

  //  if found within the immediate children
  if( isset( $array[ $pid ] ) ) return $array[ $pid ];

  //  otherwise dig deeper and recurse
  else {
    foreach( $array as $id => $arr ) {
      $find =& search_category( $pid , $arr[ 'children' ] );
      if( $find ) return $find;
    }
  }

  return FALSE;
}

EDIT: In case anyone ever runs into this problem also, here's the complete recursive solution

function &search_category( $pid , &$array ) {

  //  if found within the immediate children
  if( isset( $array[ $pid ] ) ) return $array[ $pid ];

  //  otherwise dig deeper and recurse
  else {
    foreach( $array as &$arr ) {
      $find =& search_category( $pid , $arr[ 'children' ] );
      if( $find ) return $find;
    }
  }
Community
  • 1
  • 1
Marius Miliunas
  • 1,023
  • 18
  • 34

2 Answers2

2

To have return by reference working, you need to do two things:

  1. add the & in front of the function name
  2. return a variable. You can not return FALSE:

And in your specific case you might also want to provide a reference to $array when you pass it as parameter, so add & in front of the parameter, too:

function search_category( $pid , $array ) {
     #### WRONG ####           #### WRONG ####

  //  if found within the immediate children
  if( isset( $array[ $pid ] ) ) return $array[ $pid ];
                                ### CORRECT! ###

  //  otherwise dig deeper and recurse
  else {
    foreach( $array as $id => $arr ) {
      $find =& search_category( $pid , $arr[ 'children' ] );
       ### CORRECT! ###
      if( $find ) return $find;
                  ### CORRECT! ###
    }
  }

  return FALSE;
  #### WRONG ####
}

Apart from that your code looks really complicated. I bet this can be easier solved which might also make it more easy for you to deal with the actual references. Just saying. Normally all you need to do is to reference by child ID because those children who have to parents will have the child ID as their parents ID, isn't it that way ;)

So all you need to do is to key the array by the ID and reference to it. The rest is done by PHP. That's what references are for actually.

hakre
  • 193,403
  • 52
  • 435
  • 836
  • Good one , Thanks for explaining this – Aravind.HU Dec 25 '12 at 18:14
  • In my case I need to display each category based on it's hierarchy in an html select field, so I need to organize it this way first – Marius Miliunas Dec 25 '12 at 19:12
  • I noticed I'm running into the same initial problem now, and it's within the else,foreach statement (where everything you marked is correct). It's returning the correct variable, but not as a reference – Marius Miliunas Dec 25 '12 at 19:19
  • Nevermind found it had to add an ampersand in `foreach( $array as $id => &$arr ) {` – Marius Miliunas Dec 25 '12 at 19:29
  • @MariusMiliunas: I left a general description how it works (with the fraction of the code) here: http://stackoverflow.com/a/14033570/367456 - this will make it much faster for you, too. – hakre Dec 25 '12 at 20:16
0

You need to make your function return by reference, and since you're recursing, you also need to pass your arrays by reference:

function &search_category( $pid , &$array ) {
         ^                        ^

I haven't combed through your code so there may be other problems, but that's a good starting point.

Andrew Cheong
  • 29,362
  • 15
  • 90
  • 145