简体   繁体   English

嵌套集模型的SQL查询和PHP操作

[英]SQL Query and PHP manipulation with Nested Set Model

I was reading this article, http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/ . 我正在阅读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: 我希望能够在查询然后在PHP中处理数据后以HTML显示以下结果:

"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? 您能帮助我逐步介绍一下PHP中的查询和操作以实现此结果吗?

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. 结果最终应该是一个PHP多维数组,其类别包含一个子类别数组,每个子类别包含一个子类别数组(如果存在)。

I imagine printing the depth will be very important for constructing the right tree in HTML. 我想打印深度对于在HTML中构造正确的树非常重要。

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. 基本上:读取一个节点,然后所有后面的rgt小于rgt节点都是您的孩子,请递归执行此操作。 I've used a peek / consume to read from mysql like you normally would. 我已经像往常一样使用了一个peek / consume来读取mysql的信息。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM