简体   繁体   中英

Create hierarchy of categories from woocommerce api products/categories

I am trying to create a data structure that my application can work with so I can map my categories in system to woo commerce structure. I just need a category hierarchy (shown below) that has the full path of categories with a pipe between each parent/child that has the id of the category child node.

I can easily get all the product categories in woocommerce with the following:

    $woocommerce    =   new Client($this->ecommerce_url,$this->ecommerce_api_key,$this->ecommerce_api_cred,array('wp_api' => true,'version' => 'wc/v1'));

    $send_call = true;
    $per_page = 30;
    $categories = array();
    $page = 1;

    $categories = array();

    while($send_call == true) 
    {

        $result_categories = $woocommerce->get('products/categories', array('per_page'=>$per_page, 'page'=>$page,'context' => 'view'));
        $page++;
        $categories = array_merge( $categories, $result_categories );

        if( count($result_categories) < $per_page )
        {
            $send_call=false;
        }

    }

    $return_woo_categories = array();

    foreach($categories as $index => $category)
    {
        $return_woo_categories[] = array('name' => $category['name'], 'id' => $category['id'], 'parent' => $category['parent']);
    }

var_dump of $return_woo_categories

array(13) {
  [0]=>
  array(3) {
    ["name"]=>
    string(1) "/"
    ["id"]=>
    int(23)
    ["parent"]=>
    int(20)
  }
  [1]=>
  array(3) {
    ["name"]=>
    string(1) "+"
    ["id"]=>
    int(21)
    ["parent"]=>
    int(20)
  }
  [2]=>
  array(3) {
    ["name"]=>
    string(6) "Albums"
    ["id"]=>
    int(20)
    ["parent"]=>
    int(16)
  }
  [3]=>
  array(3) {
    ["name"]=>
    string(18) "Castle On The Hill"
    ["id"]=>
    int(24)
    ["parent"]=>
    int(23)
  }
  [4]=>
  array(3) {
    ["name"]=>
    string(8) "Clothing"
    ["id"]=>
    int(14)
    ["parent"]=>
    int(0)
  }
  [5]=>
  array(3) {
    ["name"]=>
    string(7) "Hoodies"
    ["id"]=>
    int(15)
    ["parent"]=>
    int(14)
  }
  [6]=>
  array(3) {
    ["name"]=>
    string(5) "Music"
    ["id"]=>
    int(16)
    ["parent"]=>
    int(0)
  }
  [7]=>
  array(3) {
    ["name"]=>
    string(10) "My New Cat"
    ["id"]=>
    int(6)
    ["parent"]=>
    int(0)
  }
  [8]=>
  array(3) {
    ["name"]=>
    string(7) "Posters"
    ["id"]=>
    int(17)
    ["parent"]=>
    int(0)
  }
  [9]=>
  array(3) {
    ["name"]=>
    string(12) "Shape of You"
    ["id"]=>
    int(25)
    ["parent"]=>
    int(23)
  }
  [10]=>
  array(3) {
    ["name"]=>
    string(7) "Singles"
    ["id"]=>
    int(18)
    ["parent"]=>
    int(16)
  }
  [11]=>
  array(3) {
    ["name"]=>
    string(8) "T-shirts"
    ["id"]=>
    int(19)
    ["parent"]=>
    int(14)
  }
  [12]=>
  array(3) {
    ["name"]=>
    string(1) "x"
    ["id"]=>
    int(22)
    ["parent"]=>
    int(20)
  }

I need a data structure to be the following as output. (Order of keys don't matter).

$cat_map = array(
    'Clothing' => 14,
    'Clothing|Hoodies' => 15,
    'Clothing|T-shirts' => 19,
    'My New Cat' => 6,
    'Posters' => 17,
    'Music' => 16,
    'Music|Singles' => 18,
    'Music|Albums' => 20,
    'Music|Albums|x' => 22,
    'Music|Albums|/' => 23,
    'Music|Albums|+' => 21,
    'Music|Albums|/|Castle On The Hill' => 24,
    'Music|Albums|/|Shape Of You' => 25,
);

I am stuck how to do this; I would assume I would need recursion; but the thing that has me stuck is the order of the array I get back from woo commerce is not in any sort of hierarchy way. (Order of when I added with most recent first)

The easiest way would be building tree (nested) structure first and then use recursive function to concatenate strings:

$tree = array();
foreach ($return_woo_categories as $cat) {
    if (!isset($tree[$cat['id']])) { $tree[$cat['id']] = array(); }
    $tree[$cat['id']]['name'] = $cat['name'];
    if (!isset($tree[$cat['parent']])) { $tree[$cat['parent']] = array(); }
    $tree[$cat['parent']]['children'][$cat['id']] =& $tree[$cat['id']];
}

function buildPaths($tree, $path = '') {
    $result = array();
    foreach ($tree as $id => $cat) {
        $result[$id] = $path . $cat['name'];
        if (isset($cat['children'])) {
            $result += buildPaths($cat['children'], $result[$id] . '|');
        }
    }
    return $result;
}

$cat_map = buildPaths($tree[0]['children']);

This $cat_map has [id] => 'path' structure so it would have to be flipped to match your required result. Accessing paths using id is more convenient than the opposite, but if you really need this structure then last line would be:

$cat_map = array_flip(buildPaths($tree[0]['children']));

I would do a 3 level loop in order to retrieve

  1. Get parent categories
  2. Get child categories
  3. Get Child-child categories

in each loop I concatenate the "|" and then add the key => value to each Level.

The following code provides the expected array

////////////////////////////////////////////////////
 //creating new array to store new structure
 $cat_map = [] ;
//3 level loop to get desired info
foreach($return_woo_categories as $inf){
 //1 loop to get parent categories
    if($inf['parent'] == 0){
             $parentcategoryname = $inf['name'];           
            $cat_map[$parentcategoryname] = $inf['id'];          
            //2 loop to get 1 child category
                foreach($return_woo_categories as $inf2){
                    if($inf['id'] == $inf2['parent'] ){ 
                    //concat first level and second level name               
                    $firstchildname = $inf['name']."|".$inf2['name'];
                        $cat_map[$firstchildname] = $inf2['id'];                 

                    //3 loop to get 2 child category
                     foreach($return_woo_categories as $inf3){

                        if($inf2['id'] == $inf3['parent'] ){

                         $secondchildname = $inf['name']."|".$inf2['name']."|".$inf3['name'];   
                          $cat_map[$secondchildname] = $inf3['id'];    

                        }
                     }
                    }               
                }        
        }
}
//Result
var_dump( $cat_map);
array (size=11)
  'Clothing' => int 14
  'Clothing|Hoodies' => int 15
  'Clothing|T-shirts' => int 19
  'Music' => int 16
  'Music|Albums' => int 20
  'Music|Albums|/' => int 23
  'Music|Albums|+' => int 21
  'Music|Albums|x' => int 22
  'Music|Singles' => int 18
  'My New Cat' => int 6
  'Posters' => int 17

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM