使用 PHP 表示树形导航结构的最佳方式是什么?我需要能够使用面包屑轨迹跟踪树中的当前页面位置。树的某些部分是从数据库生成的,例如 make -> models。然后每个模型都有相同的等效树分支,例如:
制作 > 模型 >(区域 1、区域 2、区域 3)。
树的某些部分可能会随着时间而改变。最好有一个静态的类层次结构还是一个重用类的动态解决方案?
希望这已经得到了简单的解释。
使用 PHP 表示树形导航结构的最佳方式是什么?我需要能够使用面包屑轨迹跟踪树中的当前页面位置。树的某些部分是从数据库生成的,例如 make -> models。然后每个模型都有相同的等效树分支,例如:
制作 > 模型 >(区域 1、区域 2、区域 3)。
树的某些部分可能会随着时间而改变。最好有一个静态的类层次结构还是一个重用类的动态解决方案?
希望这已经得到了简单的解释。
从 OO 的角度来看,我建议定义如下接口:
interface BreadcrumbInterface
{
public function getLabel();
public function getParent(); // returns an instance of BreadcrumbInterface, or null
}
然后,您将创建一个 Page 类,它实现了这个接口,并且可以选择包含一个“父”,它也必须实现这个接口。这将建立您需要的层次结构。
检索完整面包屑(同时在此过程中复习您的 OO 设计模式)的一个好方法是使用访问者模式。在这种情况下,您可能希望定义一个通用抽象类以及接口,以便“抽象”处理访问者的逻辑......
abstract class BaseNode implements BreadcrumbInterface
{
protected $parent = null;
public function accept(BreadcrumbVisitor $visitor)
{
$visitor->visit($this);
}
public function setParent(BreadcrumbInterface $parent)
{
$this->parent = $parent;
}
public function getParent()
{
return $this->parent;
}
}
class BreadcrumbVisitor
{
protected $breadcrumbs = array();
public function visit(BreadcrumbInterface $node)
{
$parent = $node->getParent();
if ($parent instanceof BaseNode) {
$parent->accept($this);
}
$this->breadcrumbs[] = $node->getLabel();
}
public function getBreadcrumbs()
{
return $this->breadcrumbs;
}
}
这不会按原样运行,但希望你明白这一点。您可能还希望您的节点确定其页面的 URL 以及标签,但这可以很容易地添加。我只是想展示解决这个问题的一般 OO 结构。
编辑:
添加粗略的使用示例:
$rootPage = new Page(/*...*/);
$parentPage = new Page(/*...*/);
$parentPage->setParent($rootPage); // In reality you most likely wouldn't be building this structure so explicitly. Each object only needs to know about it's direct parent
$currentPage = new Page(/*...*/);
$currentPage->setParent($parentPage);
$visitor = new BreadcrumbVisitor();
$currentPage->accept($visitor);
$breadcrumbs = $visitor->getBreadcrumbs(); // returns an array, where the first element is the root
// then you can implode with ' > ' if you want
$breadcumbString = implode(' > ', $breadcrumbs);
class TreeNode {
/**
* the parent node
*
* @var TreeNode
*/
private $parentNode=null;
/**
* the children of this node
*
* @var TreeNode[]
*/
private $children=array();
/**
* The user element this tree node holds.
*
* @var Object
*/
private $element;
}
我会去:
$nodes
列表[如果为空,当然是叶节点];$parent
字段[如果为 null,则为根节点]。通过这种方式,您可以为每个节点重建面包屑路径,为它们提供一种getTrail()
方法:
public function getTrail()
{
$parent = $this -> parent();
$trail = array();
while($parent !== NULL)
{
// push parent element to trail
$trail[] = $parent;
// go backwards one node
$parent = $parent -> parent();
}
// you want trail in reverse order [from root to latest]
return array_reverse($trail);
}
如果您的节点类型不同,请至少提供带有/方法的TrailTrackable
接口。getTrail()
getParent()