0

I am using a PHP Class that is generating a nested categories tree menu in json format from a MySQL database. The problem is that the array used to fill the data doesn't do what it is supposed to

The PHP Class is:

class nestedCategories {
    public $json = array();

    public function generateMenu($categories,$level){
        $this->json = array();
        foreach($categories as $category ){
            $this->json['title']    = $category->description;
            $this->json['expanded'] = true;

            if(isset($category->children) && count($category->children)>0){
                $this->json['folder'] = true;
                $this->json['children'] = $this->generateMenu($category->children,$category->category_id);
            } else {
                $this->json['folder'] = false;           
            }
        }
    }
public function getJSON() { 
    return $this->json; 
}

The $json is supposed to look like:

[
    {"title": "Animalia", "expanded": true, "folder": true, "children": [
        {"title": "Chordate", "folder": true, "children": [
            {"title": "Mammal", "children": [
                {"title": "Primate", "children": [
                    {"title": "Primate", "children": [
                    ]},
                    {"title": "Carnivora", "children": [
                    ]}
                ]},
                {"title": "Carnivora", "children": [
                    {"title": "Felidae", "lazy": true}
                ]}
            ]}
        ]},
        {"title": "Arthropoda", "expanded": true, "folder": true, "children": [
            {"title": "Insect", "children": [
                {"title": "Diptera", "lazy": true}
            ]}
        ]}
    ]}
] 

but, when I am trying to pull the data from MySQL, the $json array only gives me the last pulled data from MySQL, as if it is erasing all data behind

Could someone talk me trough?

5
  • Your missing the last bracket to close your class in the Class you provided. Commented Dec 2, 2014 at 17:15
  • @battletoilet: If that was a problem, the code wouldn't even run. Commented Dec 2, 2014 at 17:16
  • 1
    What do you think happens when you execute $this->json['title'] = $category->description; inside the loop? Commented Dec 2, 2014 at 17:16
  • @FelixKling Correct, but his example is broked. Commented Dec 2, 2014 at 17:17
  • @FelixKling The class posted is not complete, it has the functions for pulling data from database, but the code that actually is throwing the error is the function posted Commented Dec 2, 2014 at 17:18

3 Answers 3

2

You are overwriting the array with each loop around categories, and wiping out the member variable with an array assignment each time round.

Plus, I suspect that it won't return the structure you're looking for unless you make it preoperly recursive (which means returning the array that you've built):

class nestedCategories {

    public function generateMenu($categories,$level){

        $categoriesJson = array();

        foreach($categories as $category ){

            $categoryJson = array();
            $categoryJson['title']    = $category->description;
            $categoryJson['expanded'] = true;

            if(isset($category->children) && count($category->children)>0){
                $categoryJson['folder'] = true;
                $categoryJson['children'] = $this->generateMenu($category->children,$category->category_id);
            } else {
                $categoryJson['folder'] = false;           
            }
            $categoriesJson[] = $categoryJson;
        }

        return $categoriesJson;
    }
}

You would now just get back the data by calling generateMenu rather than using the member variable.

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

Comments

1

You are setting $this->json = array(); at the top of your generateMenu method. When you make the recursive call it destroys what was written to the array on the previous call.

In addition in each recursive call $this->json['title'] will over write the previous title. The same goes for expanded, children and folder.

It looks like I took a little longer that I should have to make the example code. Here it is anyway.

class Foo {
    public function generateMenu($categories){
        $json_array = array();
        foreach($categories as $category) {
            $json_object = array();
            $json_object['title'] = $category->description;

            if(isset($category->children) && count($category->children)>0){
                // it looks like expanded should only be 
                // in objects with > 0 children
                $json_object['expanded'] = true;
                $json_object['folder'] = true;
                $json_object['children'] = $this->generateMenu($category->children);

            } else {
                // based on the json in the question it looks like
                // it should always contain a children array, but no folder element
                $json_object['children'] = array();           
            }
            $json_array[] = $json_object;
        }
        return $json_array;
    }
}

Here is the test data:

$Diptera = new stdClass();
$Diptera->description = 'Diptera';

$Insect = new stdClass();
$Insect->description = 'Insect';
$Insect->children = array($Diptera);

$Arthropoda = new stdClass();
$Arthropoda->description = 'Arthropoda';
$Arthropoda->children = array($Insect);

$Felidae = new stdClass();
$Felidae->description = 'Felidae';

$Carnivora2 = new stdClass();
$Carnivora2->description = 'Carnivora';
$Carnivora2->children = array($Felidae);

$Carnivora = new stdClass();
$Carnivora->description = 'Carnivora';

$Primate2 = new stdClass();
$Primate2->description = 'Primate';

$Primate = new stdClass();
$Primate->description = 'Primate';
$Primate->children = array($Primate2, $Carnivora);

$Mammal = new stdClass();
$Mammal->description = 'Mammal';
$Mammal->children = array($Primate, $Carnivora2);

$Chordate = new stdClass();
$Chordate->description = 'Chordate';
$Chordate->children = array($Mammal);

$Animalia = new stdClass();
$Animalia->description = 'Animalia';
$Animalia->children = array($Chordate);

$catagories = array($Animalia);

Here is how it's called:

$f = new Foo();
echo json_encode($f->generateMenu($catagories), JSON_PRETTY_PRINT);

Here is the output:

[
{"title": "Animalia", "expanded": true, "folder": true, "children": 
    [
    {"title": "Chordate", "expanded": true, "folder": true, "children": 
        [
        {"title": "Mammal", "expanded": true, "folder": true, "children": 
            [
            {"title": "Primate", "expanded": true, "folder": true, "children": 
                [
                {"title": "Primate", "children": []},
                {"title": "Carnivora", "children": []}
                ]
            },
            {"title": "Carnivora", "expanded": true, "folder": true, "children":
                [
                {"title": "Felidae", "children": []}
                ]
            }
            ]
        }
        ]
    },
    {"title": "Arthropoda", "expanded": true, "folder": true, "children": 
        [
        {"title": "Insect", "expanded": true, "folder": true, "children":
            [
            {"title": "Diptera", "children": []}
            ]
        }
        ]
    }
    ]
}
]

1 Comment

Even so, if I hide the {$this->json = array();{ the json response is stil the same, the data is lost and only the last record is shown
0

You are overwriting the array keys when you iterate over the JSON.

$array = array();
$array['foo'] = 'bar';
//$array['foo] = 'bar';

$array['foo'] = 'foo';
//$array['foo'] = 'foo';

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.