-2

I have the following array that I want to return as a single level so I can output it to a CSV. I need to keep the array keys. The arrays that are "children_data" I want to move to the same level as the parent array.

array(8) {
  ["id"]=>
  int(2)
  ["parent_id"]=>
  int(1)
  ["name"]=>
  string(16) "Category 1"
  ["is_active"]=>
  bool(true)
  ["position"]=>
  int(1)
  ["level"]=>
  int(1)
  ["product_count"]=>
  int(1)
  ["children_data"]=>
  array(3) {
    [0]=>
    array(8) {
      ["id"]=>
      int(2380)
      ["parent_id"]=>
      int(2)
      ["name"]=>
      string(11) "subcat 1"
      ["is_active"]=>
      bool(true)
      ["position"]=>
      int(1)
      ["level"]=>
      int(2)
      ["product_count"]=>
      int(1)
      ["children_data"]=>
      array(4) {
        [0]=>
        array(8) {
          ["id"]=>
          int(2381)
          ["parent_id"]=>
          int(2380)
          ["name"]=>
          string(11) "subsub cat 1"
          ["is_active"]=>
          bool(true)
          ["position"]=>
          int(1)
          ["level"]=>
          int(3)
          ["product_count"]=>
          int(1)
          ["children_data"]=>
          array(7) {
            [0]=>
            array(8) {
              ["id"]=>
              int(2382)
              ["parent_id"]=>
              int(2381)
              ["name"]=>
              string(21) "subsubsub cat1"
              ["is_active"]=>
              bool(true)
              ["position"]=>
              int(1)
              ["level"]=>
              int(4)
              ["product_count"]=>
              int(1)
              ["children_data"]=>
              array(19) {
                [0]=>
                array(8) {
                  ["id"]=>
                  int(2383)
                  ["parent_id"]=>
                  int(2382)
                  ["name"]=>
                  string(12) "subsubssubsubb cat1"
                  ["is_active"]=>
                  bool(true)
                  ["position"]=>
                  int(1)
                  ["level"]=>
                  int(5)
                  ["product_count"]=>
                  int(0)
                  ["children_data"]=>
                  array(4) {
                    [0]=>
                    array(8) {
                      ["id"]=>
                      int(2384)
                      ["parent_id"]=>
                      int(2383)
                      ["name"]=>
                      string(13) "subsub1"
                      ["is_active"]=>
                      bool(true)
                      ["position"]=>
                      int(1)
                      ["level"]=>
                      int(6)
                      ["product_count"]=>
                      int(0)
                      ["children_data"]=>
                      array(0) {
                      }
                    }
                    [1]=>
                    array(8) {
                      ["id"]=>
                      int(2385)
                      ["parent_id"]=>
                      int(2383)
                      ["name"]=>
                      string(10) "subsub2"
                      ["is_active"]=>
                      bool(true)
                      ["position"]=>
                      int(2)
                      ["level"]=>
                      int(6)
                      ["product_count"]=>
                      int(0)
                      ["children_data"]=>
                      array(0) {
                      }
                    }
                

What I need is:

array(8) {
  ["id"]=>
  int(2)
  ["parent_id"]=>
  int(1)
  ["name"]=>
  string(16) "Category 1"
  ["is_active"]=>
  bool(true)
  ["position"]=>
  int(1)
  ["level"]=>
  int(1)
  ["product_count"]=>
  int(1)
 array(8) {
  ["id"]=>
  int(2380)
  ["parent_id"]=>
  int(2)
  ["name"]=>
  string(11) "subcat 1"
  ["is_active"]=>
  bool(true)
  ["position"]=>
  int(1)
  ["level"]=>
  int(2)
  ["product_count"]=>
  int(1)
 array(8) {
  ["id"]=>
  int(2381)
  ["parent_id"]=>
  int(2380)
  ["name"]=>
  string(11) "subsub cat 1"
  ["is_active"]=>
  bool(true)
  ["position"]=>
  int(1)
  ["level"]=>
  int(3)
  ["product_count"]=>
  int(1)
 array(8) {
  ["id"]=>
  int(2382)
  ["parent_id"]=>
  int(2381)
  ["name"]=>
  string(21) "subsubsub cat1"
  ["is_active"]=>
  bool(true)
  ["position"]=>
  int(1)
  ["level"]=>
  int(4)
  ["product_count"]=>
  int(1)
               ETC

I need this to create a comparison between our Main DB categories and Magento categories. This way when we do a product import via the API, I can match the Magento category with our Main DB category.

Dave Hon
  • 11
  • 4
  • What have you tried so far? Where are you stuck? – waterloomatt Sep 28 '21 at 18:26
  • Does this answer your question? [How to Flatten a Multidimensional Array?](https://stackoverflow.com/questions/1319903/how-to-flatten-a-multidimensional-array) – waterloomatt Sep 28 '21 at 18:29
  • I've tried several attempts of "flattening" the array, from youtube tutorials to answers on here. The problem is, it doesn't keep the keys and output the array as one giant list rather than numerous arrays with the data in it. – Dave Hon Sep 28 '21 at 18:32
  • @waterloomatt that doesn't retain the keys and just returns a giant array with each value having a new key. I need to retain the arrays, just move them out of the ownership of the arrays theya re under. Also, don't know who downvoted my question, but that was rude. I've searched all day for a solution to this, and I can't find anything on StackOverflow or youtube about this specific case. – Dave Hon Sep 28 '21 at 18:38
  • Consider using `var_export($arr)` on your source array to facilitate volunteers that want to replicate and possibly help. – berend Sep 28 '21 at 18:47
  • hidden inside a comment on the page that @waterloomatt linked, is a version of a recursive function that keeps the keys intact: `function flatten(array $array) { $return = array(); array_walk_recursive($array, function($a,$b) use (&$return) { $return[$b] = $a; }); return $return; } `. Not tested, might work. – jibsteroos Sep 28 '21 at 18:50
  • @jibsteroos that only returns the last item in the array, but ti does keep the keys. Here it is: array(7) { ["id"]=> int(3475) ["parent_id"]=> int(3468) ["name"]=> string(5) "FAQ's" ["is_active"]=> bool(true) ["position"]=> int(7) ["level"]=> int(3) ["product_count"]=> int(0) } – Dave Hon Sep 28 '21 at 18:56
  • That's because it is completely flattening the array and preserving the keys. Your _children_data_ elements have keys of `0` so it is overwriting the ones before it. You need a custom function that knows to bring your _children_data_ and use a custom key, but you also need to show an attempt before some will be willing to help you out. Might I suggest you rethink _why_ you are trying to flatten the array and perhaps use a different data type. Could you not write a query? Use JSON object? – waterloomatt Sep 28 '21 at 19:02
  • I am trying to flatten the array because I have a list of over 700 categories (including parents and children) and I need the ID, parent ID, and name in a CSV to draw up a comparison table in a spreadsheet. The spreadsheet will be used in a reference to connect the two databases. I can't do a direct comparison between the two, because the Name fields for the categories are slightly different (one accepts certain characters, the other does not.) Every attempt I've tried has already been documented here, and I'm not going to repost. It's boggling there isn't a simple solution. – Dave Hon Sep 28 '21 at 19:11
  • I ended up using array_chunk to separate out the array into smaller arrays to feed into the CSV. – Dave Hon Sep 28 '21 at 19:48
  • Please provide enough code so others can better understand or reproduce the problem. – Community Oct 06 '21 at 15:24

1 Answers1

0

There are a lot of good examples in the question linked by @waterloomatt, but that is a question that specifically asks "how to do this without using recursion".

The simplest way to turn your nested category tree into a flattened array is to use recursion:

function flatten($array, &$result) {
    foreach ($array as $item) {
        $children = $item['children_data'] ?? array();
        unset($item['children_data']);

        $result[] = $item;
        flatten($children, $result);
    }
}

$flattened = array();
flatten($categories, $flattened);

Note that this does require $categories to be an array that's nested one more level than your var_dump() sample data, so:

$categories = array(
    0 => array(
        "id" => 2,
        "parent_id" => 1,
        "name" => "Category 1",
        "is_active" => true,
        "position" => 1,
        "level" => 1,
        "product_count" => 1,
        "children_data" => array(
            0 => array(
                "id" => 2380,
                "parent_id" => 2,
...etc

This will give you the array you want, which you can then iterate over to output it into your CSV file:

var_export($flattened);

array (
  0 => 
  array (
    'id' => 2,
    'parent_id' => 1,
    'name' => 'Category 1',
    'is_active' => true,
    'position' => 1,
    'level' => 1,
    'product_count' => 1,
  ),
  1 => 
  array (
    'id' => 2380,
    'parent_id' => 2,
    'name' => 'subcat 1',
    'is_active' => true,
    'position' => 1,
    'level' => 2,
    'product_count' => 1,
  ),
  2 => 
  array (
    'id' => 2381,
    'parent_id' => 2380,
    'name' => 'subsub cat 1',
    'is_active' => true,
    'position' => 1,
    'level' => 3,
    'product_count' => 1,
  ),
  3 => 
  array (
    'id' => 2382,
    'parent_id' => 2381,
    'name' => 'subsubsub cat1',
    'is_active' => true,
    'position' => 1,
    'level' => 4,
    'product_count' => 1,
  ),
  4 => 
  array (
    'id' => 2383,
    'parent_id' => 2382,
    'name' => 'subsubssubsubb cat1',
    'is_active' => true,
    'position' => 1,
    'level' => 5,
    'product_count' => 0,
  ),
  5 => 
  array (
    'id' => 2384,
    'parent_id' => 2383,
    'name' => 'subsub1',
    'is_active' => true,
    'position' => 1,
    'level' => 6,
    'product_count' => 0,
  ),
  6 => 
  array (
    'id' => 2385,
    'parent_id' => 2383,
    'name' => 'subsub2',
    'is_active' => true,
    'position' => 2,
    'level' => 6,
    'product_count' => 0,
  ),
)
rickdenhaan
  • 10,857
  • 28
  • 37