John P
John P

Reputation: 1221

PHP make tree-structured array from 4 arrays

I have on a page categories (represented as checkboxes). On the next page I have subcategories of categories from 1st page. On the next page sub-categories for elements in the 2nd page and so on. I save all the selected items in arrays representing the choices made in different levels.The problem is that I don't know how to make a tree structure from all these arrays. Let me say what I have at the moment:

I have 4 arrays, lets imagine them as 4 levels (each level represents checkboxes selected on the # page). I keep in them the checkboxes selected by the user. Here is an example of data: (the value represents the id of the item in the database)

The l1 value of $_SESSION['0'] is '1' 

The l2 value of $_SESSION['0'] is '2' 
The l2 value of $_SESSION['1'] is '3' 

The l3 value of $_SESSION['0'] is '3' 
The l3 value of $_SESSION['1'] is '4' 
The l3 value of $_SESSION['2'] is '5' 
The l3 value of $_SESSION['3'] is '6' 

The l4 value of $_SESSION['0'] is '1' 
The l4 value of $_SESSION['1'] is '2' 
The l4 value of $_SESSION['2'] is '3' 
The l4 value of $_SESSION['3'] is '4' 
The l4 value of $_SESSION['4'] is '5' 

For each id in the database I have the id of the item it belongs to (for eg: level 2: )

id=1; name = programming, category_id = 1;

I can find the relationships by querying the database.

in the case above the both elements from l2 are subcategories of l1[0]. First 2 elements from level 3 are subcategories of l2[0] and last 2 elements are subcategories of l2[1], and in level 4 some of them are subcategories of something in level 3 (not every element may have subcategories).

How can I build the tree-structured JSON for all this data? Any ideas or suggestions? Thank you!

Upvotes: 3

Views: 169

Answers (1)

Dominique Vienne
Dominique Vienne

Reputation: 415

First of all, please apologize if I do not understand well your problem.

Let me explain your problem the way I understand it:

First page

You display a form which contains checkbox with name "category" and values are ids of the specific main category

On second page landing

You populate an array (I would call it $_SESSION['categories_checked']) with check categories

On second page

You display subcategories of level 1 the same way you display categories on main page. Let's say form element name is "subcat1"

On third page landing

You populate an array (I would call it $_SESSION['subcats1_checked']) with check subcategories

On third page

You display subcategories of level 2 the same way you display categories on main page. Let's say form element name is "subcat2"

On fourth page landing

You populate an array (I would call it $_SESSION['subcats2_checked']) with check subcategories

On fourth page

You display subcategories of level 3 the same way you display categories on main page. Let's say form element name is "subcat3"

On final page landing

You populate an array (I would call it $_SESSION['subcats3_checked']) with check subcategories

My answer

From my point of view, I would rather do the following:

  • always use same variable name (in HTML forms and in PHP) so the code could be greatly improved
  • optionnaly use a hidden form element which would contain the level
  • nest your arrays

    $_SESSION['categories'] = [
          3 => [
                56 => [
                     89 => [
                           121 => [1,2,3,4,5,],
                           ],
                      ],
               ],
    ];
    

This representation seems to be closer to the reality and should be easier to display.

Next step is to create a recursive function at which you will pass the resulting array of a one step form and the $_SESSION['categories'] variable.

Let me know if the solution is the right way for you... I could give you a hand if necessary.

So, recursion is the success key but...

Something is missing... In order to treat your results and have the PHP array I mentionned, you will have to construct your forms that way:

First page

<input type="checkbox" name="category[0]" value="1" /> Cat1 name
<input type="checkbox" name="category[0]" value="2" /> Cat2 name

Second page

Subcats of cat 1
<input type="checkbox" name="category[1]" value="110" /> SubCat1 name
<input type="checkbox" name="category[1]" value="222" /> SubCat2 name

Subcats of cat 2
<input type="checkbox" name="category[2]" value="110" /> SubCat1 name
<input type="checkbox" name="category[2]" value="222" /> SubCat2 name

This way, you would be able to avoid level input element because subcategory is now only defined by its parent. Of course, this implies that every category and subcategory have a different ID (trick is possible if it is not the case).

Here is a quick and dirty code that should help you

<?php
/**
 * Created by PhpStorm.
 * User: dvienne
 * Date: 31/05/2017
 * Time: 15:16
 */
function treatCategories($parentCatId, $selectedId, $categories) {
  foreach($categories as $categoryID => $category) {
    if(empty($category) AND ($categoryID==$parentCatId)) {
      $categories[$categoryID][$selectedId] = [];
      break;
    } elseif(is_array($category) AND empty($category)) {
      /** RECURSION */
      treatCategories($parentCatId, $selectedId, $category);
    }
  }

  $_SESSION['categories'] = $categories;
}


$userSelection  = $_POST['categories'];
$level          = $_POST['level'];
if(!empty($_SESSION['categories'])) {
  $categories = $_SESSION['categories'];
} else {
  $categories = [];
}

if(!empty($categories)) {
  foreach($userSelection as $parentCatId => $selectedId) {
    treatCategories($parentCatId, $selectedId, $categories);
  }
} else {
  foreach($userSelection as $catId) {
    $categories[$catId] = [];
  }

  $_SESSION['categories'] = $categories;
}

PLEASE BE AWARE

This is clearly not a optimized way to treat data because script will have to scan entire category array before inserted its value. You should perhaps consider a one page solution using AJAX queries.

Upvotes: 1

Related Questions