SQL Query и PHP-манипуляция с помощью модели вложенного набора

Я читал эту статью, http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/ .

Я хотел привести простой пример, а затем спросить, как мне получить желаемый результат? Итак, вот пример:

+---------+-----------------------------+ | 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 | +-------------+--------------------+------+------+ 

Я хочу иметь возможность отображать следующий результат в HTML после запроса, а затем манипулировать данными в PHP:

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

Можете ли вы помочь мне пройти через запрос и манипуляции в PHP для достижения этого результата?

Некоторые особенности, о которых нужно подумать:

  1. Обратите внимание, что обе категории находятся под электроникой, но «Электроника» появляется только один раз здесь, отображая каждую из подкатегорий, которые она принадлежит ниже
  2. Результатом должен стать многомерный массив PHP с категорией, содержащей массив подкатегорий, и каждая подкатегория содержит массив подкатегорий, если они существуют.

Я предполагаю, что печать глубины будет очень важна для построения правильного дерева в HTML.

    Я думал, что это хороший вызов. Вот мое решение:

    В основном: прочитайте узел, тогда все следующие узлы с rgt меньшим, чем ваш rgt являются вашими детьми, сделайте это рекурсивно. Я использовал peek / consume для чтения из mysql, как обычно.

    Сценарий будет разорваться или зациклиться, если запрос не даст никаких результатов или если набор данных сломан .

     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());