繁体   English   中英

PHP分层导航OOP结构

[英]PHP Hierarchical Navigational OOP structure

用PHP表示树形导航结构的最佳方法是什么? 我需要能够使用面包屑痕迹跟踪树中的当前页面位置。 树的一部分是从数据库(例如make->模型)生成的。 每个模型都具有相同的等效树分支,例如:

制作>模型>(区域1,区域2,区域3)。

树的某些部分可能会随着时间变化。 最好是具有静态的类层次结构或动态的解决方案,以重新使用类?

希望对此进行简单的解释。

我会去:

  • 每个元素的$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);

}

如果您的节点类型不同,请至少至少使用getTrail() / getParent()方法提供TrailTrackable接口。

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;
}

从面向对象的角度来看,我建议定义如下接口:

interface BreadcrumbInterface
{
    public function getLabel();

    public function getParent(); // returns an instance of BreadcrumbInterface, or null
}

然后,您将创建一个Page类,该类实现此接口,并且可以选择包含一个“父级”,该父级也必须实现此接口。 这将建立您需要的层次结构。

检索完整的面包屑(在此过程中梳理OO设计模式的一种很好的方法)是使用visitor模式 在这种情况下,您可能想定义一个通用的抽象类以及接口,以便“抽象”处理访问者的逻辑。

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以及标签,但这可以很容易地添加。 我只是想展示解决此问题的一般面向对象结构。

编辑:

添加粗略用法示例:

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

暂无
暂无

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

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