所以我认为我的问题归结为两个问题:
当树存储在 MySQL 中(在两个表之间)时,如何使用邻接列表模型方法在 PHP 中构建可遍历的树结构,同时牢记性能?
什么是一种可维护的方法来以所需的格式显示树而不复制遍历代码并用 if/else 和 switch 语句乱扔逻辑?
以下是更多详细信息:
我正在使用 Zend 框架。
我正在处理一份问卷。它存储在两个单独的表之间的 MySQL 数据库中:questions 和 question_groups。每个表都扩展了适当的 Zend_Db_Table_* 类。层次结构使用邻接列表模型方法表示。
我意识到我遇到的问题可能是由于我将树结构填充到 RDBMS 中,所以我对替代方案持开放态度。但是,我还存储了问卷调查对象和他们的回答,因此需要替代方法来支持这一点。
问卷需要以各种 HTML 格式显示:
- 作为输入响应的表单(使用 Zend_Form)
- 作为带有问题(和某些组)的有序列表(嵌套),作为按问题或按组查看响应的链接。
- 作为一个有序列表(嵌套),每个问题都附加了回复。
问题是叶节点,question_groups 可以包含其他 question_groups 和/或问题。加起来,有超过 100 行需要处理和显示。
目前,我有一个视图助手,它使用递归进行所有处理以检索 question_group 的子项(一个在两个表之间执行 UNION 的查询:QuestionGroup::getChildren($id))。此外,当显示带有问题响应的问卷时,需要额外的两个查询来检索受访者及其对每个问题的回答。
虽然页面加载时间不是很长,但这种方法感觉不对。递归加上几乎每个节点的多个数据库查询,并没有让我内心感到很温暖和模糊。
我已经在从 UNION 返回的完整树数组上尝试了无递归和递归方法,以构建一个分层数组来遍历和显示。但是,由于组和问题存储在单独的表中,因此存在重复的节点 ID,这似乎被打破了。也许我在那里遗漏了一些东西......
目前,以上面列出的格式显示树的逻辑相当混乱。我不想到处重复遍历逻辑。然而,到处都是条件语句也不会产生最容易维护的代码。我已经阅读了有关访问者、装饰器和一些 PHP SPL 迭代器的信息,但我仍然不清楚它们如何与扩展 Zend_Db_Table、Zend_Db_Table_Rowset 和 Zend_Db_Table_Row 的类一起工作。特别是因为我还没有解决以前从数据库构建层次结构的问题。稍微轻松地添加新的显示格式(或修改现有的)会很好。