我对我的作品弹出菜单的结构使用分层存储,类似于您正在寻找的内容。表结构如下:
CREATE TABLE IF NOT EXISTS `page_menu` (
`menu_id` int(5) NOT NULL AUTO_INCREMENT,
`menu_parent` int(5) DEFAULT NULL,
`menu_sibling` int(5) DEFAULT NULL,
`lang` char(2) NOT NULL,
`url_id` int(10) NOT NULL,
PRIMARY KEY (`menu_id`),
KEY `menu_parent` (`menu_parent`),
KEY `menu_sibling` (`menu_sibling`),
KEY `url_id` (`url_id`),
KEY `lang` (`lang`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `page_menu`
ADD CONSTRAINT `page_menu_ibfk_1` FOREIGN KEY (`menu_parent`) REFERENCES `page_menu` (`menu_id`) ON DELETE SET NULL ON UPDATE CASCADE,
ADD CONSTRAINT `page_menu_ibfk_2` FOREIGN KEY (`menu_sibling`) REFERENCES `page_menu` (`menu_id`) ON DELETE SET NULL ON UPDATE CASCADE,
ADD CONSTRAINT `page_menu_ibfk_3` FOREIGN KEY (`url_id`) REFERENCES `page_desc` (`url_id`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `page_menu_ibfk_4` FOREIGN KEY (`lang`) REFERENCES `lang` (`lang`) ON DELETE CASCADE ON UPDATE CASCADE;
所以基本上每条记录都有自己唯一的 id (menu_id),并且还列出了一个可选的父级(根元素为 NULL)和可选的老兄弟(最老的兄弟也为 NULL)这两者都是 menu_id 主键列的外键强制菜单元素与其他现有菜单元素关联,最后是 url 本身的语言和 id,它们链接到其他表,这些表保存页面的每个语言版本的页面数据。
因此,虽然行看起来像这样:
它拥有的结构是这样的:
<ul>
<li>1</li>
<li>11
<ul>
<li>61
<ul>
<li>111</li>
<li>121</li>
</ul>
</li>
<li>71</li>
</ul>
</li>
<li>21</li>
<li>31</li>
<li>41</li>
<li>51</li>
</ul>
这种方法的缺点是您不能单独使用 SQL 提取树,它需要一些处理才能以正确的顺序对记录进行排序,然后才能轻松地重建树。基本上,您必须循环遍历结果以将它们重新排序为树的扁平版本,然后才能将其反向附加到父母中。虽然速度不是很慢,但这也不是很快,因此它可能不是适合的方法无法静态缓存在文件中的复杂树。但是对于简单的事情,比如偶尔重新创建弹出菜单的嵌套结构(保存为 html 包含文件),它的效果很好。