使用 Doctrine NestedSet 进行面包屑导航

发布于 2024-11-07 12:22:09 字数 577 浏览 0 评论 0原文

我有一个实现 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>

I have a model that implements NestedSet behaviour:

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

Example fixtures:

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

I am looking for the easiest way to implement breadcrumb navigation (trail). For example, for Page_3 navigation will look like this:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

断念 2024-11-14 12:22:09

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

//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() 。它只是没有任何语义意义。

Since I hate having any kind of logic in templates (and partials), here's my slightly improved version.

//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; ?>

So, all the logic for building a url is now in Page::getPath() method.

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

What I don't like it having to pass $parent to Page::getPath(). It just doesn't make any semantical sense.

追风人 2024-11-14 12:22:09

与另一个问题几乎相同,但您必须添加一个“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()?因为你的网址似乎暗示着递归。

Almost the same as in the other question, but you have to add a 'parentUrl' variable :

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

Feed it the root of your tree as $node (hydrate it hierarchically), the node of the current page as $pageNode, and '' as $currentNodeUrl and add ' > ' and the link to the current page.

Why does this solution use recursion and not getAncestors()? Because your urls seem to imply recursion.

浅忆流年 2024-11-14 12:22:09

另一个答案,更简单(也许更有效),使用 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));
}

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

Another answer, more simple (and perhaps more efficient), with getAncestors() and recursion:

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

Call this with an array of ancestor nodes or find a way to pop a Doctrine_Collection if you want to use it with getAncestors() directly.
Again, all your problem comes from the fact that your urls are recursively computed, it would be simpler and faster to display if you had a colum path with the current url (but then you would have to compute, update it), etc... consider doing this if you have more reads than writes (if your tree does not change often).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文