1

I was reading this article, http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/.

I wanted to give a simple example and then ask you how do I get the desired result? So here is the example:

+---------+-----------------------------+
|  product_id | product_name            |
+---------+-----------------------------+
|           1 | Example Product         |
+---------+-----------------------------+
+---------+-----------------------------+
|  product_id | category_id             | 
+---------+-----------------------------+
|           1 | 2                       |
|           1 | 4                       |
+---------+-----------------------------+
+-------------+--------------------+------+------+
| category_id | name                 | lft | rgt |
+-------------+--------------------+------+------+
|           1 | Electronics          |  1  |  8  |
|           2 | Televisions          |  2  |  3  |
|           3 | Portable Electronics |  4  |  7  | 
|           4 | CD Players           |  5  |  6  |
+-------------+--------------------+------+------+

I want to be able to display the following result in HTML after querying and then manipulating the data in PHP:

"Example Product" Categories:
Electronics
    Televisions 
    Portable Electronics
        CD Players

Can you help walk me through the query and manipulation in PHP to achieve this result?

Some specifics to think about:

  1. Notice how both categories are under Electronics, but "Electronics" appears only once here, displaying each of the subcategories it belongs to below
  2. The result should eventually be a PHP multi-dimensional array with the category containing an array of sub-categories and each sub-category containing an array of sub-subcategories if they exist.

I imagine printing the depth will be very important for constructing the right tree in HTML.

0

1 Answer 1

4

I thought this was a nice challenge .. here's my solution:

Basically: read a node, then all following nodes with a rgt smaller than your rgt are your children, do this recursively. I've used a peek/consume to read from mysql like you normally would.

The script will break or loop if the query gives no results, or if the data-set is broken.

class NestedNodeReader {

    private $mysql_result;
    private $peeked = false;
    private $last_peek;

    public function __construct($mysql_result) {
        $this->mysql_result = $mysql_result;
    }

    public function getTree() {
        $root = $this->consume();
        $root["children"] = $this->getSubTree($root["rgt"]);
        return $root;
    }

    private function getSubTree($stop_at) {
        $nodes = array();
        $node = $this->peek();
        while ($node["rgt"] < $stop_at) {
            $node = $this->consume();
            $node["children"] = $this->getSubTree($node["rgt"]);
            $nodes[] = $node;
            $node = $this->peek();
            if (false === $node) {
                break;
            }
        }
        return $nodes;
    }

    private function peek() {
        if (false === $this->peeked) {
            $this->peeked = true;
            $this->last_peek = mysql_fetch_assoc($this->mysql_result);
        }
        return $this->last_peek;
    }

    private function consume() {
        if (false === $this->peeked) {
            return mysql_fetch_assoc($this->mysql_result);
        } else {
            $this->peeked = false;
            return $this->last_peek;
        }
    }
}

$query = "SELECT node.name, node.lft, node.rgt
    FROM nested_category AS node,
        nested_category AS parent
    WHERE node.lft BETWEEN parent.lft AND parent.rgt
        AND parent.name = 'ELECTRONICS'
    ORDER BY node.lft;"
$mysql_result = mysql_query($query);
$nnr = new NestedNodeReader($mysql_result);
print_r($nnr->getTree());
Sign up to request clarification or add additional context in comments.

1 Comment

Good effort! Sorry the OP didn't reply to you at the time... :-(.

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.