Breadcrumb navigation with Doctrine NestedSet

前端 未结 3 327
半阙折子戏
半阙折子戏 2021-01-26 15:29

I have a model that implements NestedSet behaviour:

Page:
  actAs:
    NestedSet:
      hasManyRoots: true
      rootColumnName: root_id
  columns:
    slug: str         


        
相关标签:
3条回答
  • 2021-01-26 16:22

    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).

    0 讨论(0)
  • 2021-01-26 16:31

    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.

    0 讨论(0)
  • 2021-01-26 16:31

    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.

    0 讨论(0)
提交回复
热议问题