【问题标题】:Breadcrumb navigation with Doctrine NestedSet使用 Doctrine NestedSet 进行面包屑导航
【发布时间】:2011-05-15 14:57:24
【问题描述】:

我有一个实现 NestedSet 行为的模型:

Page:
  actAs:
    NestedSet:
      hasManyRoots: true
      rootColumnName: root_id
  columns:
    slug: string(255)
    name: string(255)

夹具示例:

Page:
  NestedSet: true
  Page_1:
    slug: slug1
    name: name1
  Page_2:
    slug: slug2
    name: name2
    children:
      Page_3:
        slug: page3
        name: name3

我正在寻找实现面包屑导航(轨迹)的最简单方法。例如,对于 Page_3,导航将如下所示:

<a href="page2">name2</a> > <a href="page2/page3>name3</a>

【问题讨论】:

  • 第1页和第2页的slug是不是你弄错了?不应该是 page1 和 page2 吗?

标签: symfony1 doctrine nested-sets doctrine-1.2


【解决方案1】:

由于我讨厌在模板(和部分)中包含任何类型的逻辑,所以这是我稍微改进的版本。

//module/templates/_breadcrumbElement.php
<?php foreach ($node as $child): ?>
<li>
  <a href="<?php echo $child->getPath($parent) ?>"><?php echo $child->getName() ?></a>
  <?php if (count($child->get('__children')) > 0): ?>
    <ul>
      <?php include_partial('node', array('node' => $child->get('__children'), 'parent' => $child)) ?>
    </ul>
  <?php endif; ?>
</li>
<?php endforeach; ?>

所以,构建 url 的所有逻辑现在都在 Page::getPath() 方法中。

class Page extends BasePage
{
  /**
   * Full path to node from root
   *
   */
  protected $path = false;

  public function __toString()
  {
    return $this->getSlug();
  }
  public function getPath($parent = null)
  {
    if (!$this->path)
    {
      $this->path = join('/', null !== $parent ? array($parent->getPath(), $this) : array($this));
    }
    return $this->path;
  } 
}

我不喜欢将 $parent 传递给 Page::getPath()。它只是没有任何语义意义。

【讨论】:

    【解决方案2】:

    与其他问题几乎相同,但您必须添加一个“parentUrl”变量:

    //module/templates/_breadcrumbElement.php
    foreach ($node->get('__children') as $child) :
      if ($child->isAncestorOf($pageNode)):
         $currentNodeUrl = $parentUrl . $child->getSlug() . '/';
         echo link_to($child->getName(), $currentNodeUrl) . ' > ' ;
         include_partial('module/breadcrumbElement', array('node' => $child, 'pageNode' => $pageNode, 'parentUrl' => $currentNodeUrl));
      endif;
    endforeach;
    

    将树的根作为$node(分层水合),将当前页面的节点作为$pageNode,将''作为$currentNodeUrl,并添加'>'和指向当前页面的链接.

    为什么这个解决方案使用递归而不是getAncestors()?因为您的网址似乎暗示着递归。

    【讨论】:

    • 很好,递归就是这样。谢谢。
    【解决方案3】:

    另一个答案,更简单(也许更有效),使用 getAncestors() 和递归:

    //module/templates/_breadcrumbElement.php
    if ($node = array_pop($nodes)) // stop condition
    {
        $currentNodeUrl = $parentUrl . $node->getSlug() . '/';
        echo link_to($node->getName(), $currentNodeUrl) . ' > ' ;
        include_partial('module/breadcrumbElement', array(
          'nodes' => $nodes, 'parentUrl' => $currentNodeUrl));
    }
    

    如果您想直接将其与getAncestors() 一起使用,请使用一组祖先节点调用它或找到一种弹出Doctrine_Collection 的方法。 同样,您所有的问题都来自于您的 url 是递归计算的事实,如果您有一个带有当前 url 的列路径(但是您必须计算、更新它)等,那么显示会更简单、更快。 . 如果您的读取次数多于写入次数(如果您的树不经常更改),请考虑这样做。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多