Php 两表邻接表模型
因此,我认为我的问题归结为两个问题:Php 两表邻接表模型,php,zend-framework,tree,hierarchical-data,adjacency-list-model,Php,Zend Framework,Tree,Hierarchical Data,Adjacency List Model,因此,我认为我的问题归结为两个问题: 当树存储在MySQL(两个表之间)中时,如何使用邻接列表模型方法在PHP中构建可遍历的树结构,同时考虑性能 以所需格式显示树的可维护方法是什么,而不必重复遍历代码,也不必使用if/else和switch语句来乱丢逻辑 详情如下: 我正在使用Zend框架 我正在做一份调查问卷。它存储在一个MySQL数据库中,位于两个单独的表之间:问句和问句组。每个表都扩展了相应的Zend_Db_table_*类。层次结构使用邻接列表模型方法表示 我意识到我遇到的问题很可能是因
- 邻接列表通常在每一行中为您提供一个
列,该列将一行链接到其直接父行。如果行是树的根,parent\u id
为空。但这会导致您运行许多SQL查询,这非常昂贵parent\u id
- 添加另一列
,这样每一行都知道它所属的树。这样,您就可以通过一个SQL查询获取给定树的所有节点。在root\u id
类中添加一个方法,通过树的根id获取表
行集
class QuestionGroups extends Zend_Db_Table_Abstract { protected $_rowClass = 'QuestionGroup'; protected $_rowsetClass = 'QuestionGroupSet'; protected function fetchTreeByRootId($root_id) { $rowset = $this->fetchAll($this ->select() ->where('root_id = ?', $root_id) ->order('id'); ); $rowset->initTree(); return $rowset; } }
- 编写一个扩展
的自定义类,并编写函数来检索给定行的父行及其子行的Zend\u Db\u Table\u Row
。Rowset
类应包含受保护的数据对象,以引用父对象和子对象数组。行
对象还可以具有用于面包屑的行
函数和getLevel()
函数getAncestorsRowset()
class QuestionGroup extends Zend_Db_Table_Row_Abstract { protected $_children = array(); protected $_parent = null; protected $_level = null; public function setParent(Zend_Db_Table_Row_Abstract $parent) { $this->_parent = $parent; } public function getParent() { return $this->_parent; } public function addChild(Zend_Db_Table_Row_Abstract $child) { $this->_children[] = $child; } public function getChildren() { return $this->_children; } public function getLevel() {} public function getAncestors() {} }
- 编写一个自定义类扩展
,该类具有迭代行集中的行的函数,设置父引用和子引用,以便随后可以将它们作为树进行遍历。另外,Zend_Db_Table_Rowset
应该有一个Rowset
函数getRootRow()
class QuestionGroupSet extends Zend_Db_Table_Rowset_Abstract { protected $_root = null; protected function getRootRow() { return $this->_root; } public function initTree() { $rows = array(); $children = array(); foreach ($this as $row) { $rows[$row->id] = $row; if ($row->parent_id) { $row->setParent($rows[$row->parent_id]); $rows[$row->parent_id]->addChild($row); } else { $this->_root = $row; } } } }
现在可以对行集调用
getRootRow()
,它将返回根节点。拥有根节点后,可以调用getChildren()
并在其上循环。然后,您也可以对这些中间子级中的任何一个调用getChildren()
,并以任意格式递归输出一个树。谢谢,比尔。我在这两个表中都添加了一个root_id列,并实现了您建议的方法()。但我看不到全局。遍历行集中的行的方法如何处理分布在两个表中的树?我假设fetchTreeByRootId()需要使用联合。或者创建视图是更好的解决方案?虽然我很喜欢能够利用现有的课程…比尔,谢谢你的澄清。它工作得很好。我仍在努力将叶子(问题)整合到组合中。完成后,我将发布我的最终解决方案。希望能让其他可能遇到同样情况的人受益。我很高兴这对你有用。顺便说一句,我将上面的initTree()
更改为public
函数,因为它必须由Table类调用。你可能已经找到了同样的东西。