Навигация Zend (контейнер) — removePage() не является рекурсивной

#php #zend-framework #recursion #zend-navigation

#php #zend-framework #рекурсия #zend-навигация

Вопрос:

Zend_Navigation расширяется Zend_Navigation_Container . Все функции findOneBy() , findAllBy() и findBy() выполняют рекурсивный поиск страниц, но removePage() этого не делает. Это означает, что $navigation->removePage($navigation->findOneBy('id', 'page_10')); будет работать, ТОЛЬКО если page_10 является узлом навигации корневого уровня. Кто-нибудь еще сталкивался с этим и нашел обходной путь?


Я нашел свои собственные решения и принял одно из них за то, как я его реализовал. Я выберу решение у кого-нибудь другого, если оно лучше моего.

Ответ №1:

Расширяйте Zend_Navigation и Zend_Navigation_Container для рекурсивного удаления страниц.

Создайте, My_Navigation_Container которое расширяет Zend_Navigation_Container :

 abstract class My_Navigation_Container extends Zend_Navigation_Container
{
    /**
     * Remove page(s) matching $property == $value
     *
     * @param string $property
     * @param mixed $value
     * @param bool $all
     * @return My_Navigation_Container
     */
    public function removeBy($property, $value, $all = false)
    {
        $pages = array();

        if ($all) {
            $pages = $this->findAllBy($property, $value);
        } else {
            if ($page = $this->findOneBy($property, $value)) {
                $pages[] = $page;
            }
        }

        foreach ($pages as $page) {
            $this->removePageRecursive($page);
        }

        return $this;
    }


    /**
     * Recursively removes the given page from the container
     *
     * @param Zend_Navigation_Page $page
     * @return boolean
     */
    public function removePageRecursive(Zend_Navigation_Page $page)
    {
        if ($this->removePage($page)) {
            return true;
        }

        $iterator = new RecursiveIteratorIterator($this, RecursiveIteratorIterator::SELF_FIRST);
        foreach ($iterator as $pageContainer) {
            if ($pageContainer->removePage($page)) {
                return true;
            }
        }

        return false;
    }
}
  

Создайте копию, Zend_Navigation которая расширяет My_Navigation_Container :

 class My_Navigation extends My_Navigation_Container
{
    /**
     * Creates a new navigation container
     *
     * @param array|Zend_Config $pages    [optional] pages to add
     * @throws Zend_Navigation_Exception  if $pages is invalid
     */
    public function __construct($pages = null)
    {
        if (is_array($pages) || $pages instanceof Zend_Config) {
            $this->addPages($pages);
        } elseif (null !== $pages) {
            throw new Zend_Navigation_Exception('Invalid argument: $pages must be an array, an instance of Zend_Config, or null');
        }
    }
}
  

Ответ №2:

Найдите родительский файл, а затем удалите дочерний. Для этого требуется знание родительских атрибутов:

 $navigation->findOneBy('id', 'parent_id')
        ->removePage($navigation->findOneBy('id', 'child_id'));