Проблема Zend Navigation и Zend Router - не удается найти правильную активную страницу - PullRequest
3 голосов
/ 03 сентября 2010

Хорошо.Я создаю CMS с Zend.Это не так просто, как кажется, но все же - лучшее решение для меня.У меня есть древовидная система с метками ID и PARENT, PARENT, под которой находится ребенок.Тем не мение.Простые вещи.

Каждый раз, когда страница создается или сортируется, навигация и маршруты регенерируются.

Я скопирую весь код Admin_Pages_Model для создания здесь навигации и маршрутов.

Навигация создается здесь: (я думаю, что информация о модуле / контроллере / действии не нужна, потому что она загружается из маршрутизатора)

    public function createNavigation($locale = false){  
    $root = $this->getRoot($locale);

    $navigation = array();
    $router = array();

    foreach($root as $row){

        $navigation[$row["id"]] = array(
            "label" => $row["name"],
            "module" => "frontend",
            "controller" => "page",
            "action" => "show",
            "route" => "route_".$row["id"],
            "visible" => (boolean) $row["active"],
            "lastmod" => ($row["modified"] ? $row["modified"] : $row["created"])
        );

        $children = $this->getChildren($row["id"]);

        if(count($children)){
            foreach($children as $child){

                $navigation[$row["id"]]["pages"][$child["id"]] = $this->_createNavigation($child["id"]);

            }
        }

    }

    $nav = new Zend_Navigation(new Zend_Config($navigation));

    $this->createRoutes();

    if(!$locale){
        Crcms_Config::setConfig("navigation_sitemap", $nav->toArray());
    } else {
        Crcms_Config::setConfig("navigation_".$locale, $nav->toArray());
    }
}
private function _createNavigation($id){
    $page = $this->getPage($id);

    $navigation = array(
        "label" => $page["name"],
        "module" => "frontend",
        "controller" => "page",
        "action" => "show",
        "route" => "route_".$page["id"],
        "visible" => (boolean) $page["active"],
        "lastmod" => ($page["modified"] ? $page["modified"] : $page["created"])
    );

    $children = $this->getChildren($page["id"]);

    if(count($children)){
        foreach($children as $child){

            $navigation["pages"][$child["id"]] = $this->_createNavigation($child["id"]);

        }
    }

    return $navigation;
}

В конце - перед сохранением навигации в базе данных она вызывает $ this->createRoutes ();Вот код:

    public function createRoutes(){
    $root = $this->getRoot($locale);

    foreach($root as $row){

        $slugPath = "/".$row["slug"]."";

        $router["route_".$row["id"]] = array(
            "route" => $slugPath.".html",
            "defaults" => array(
                "pageId" => $row["id"],
                "locale" => $row["locale"],
                "module" => "frontend",
                "controller" => "page",
                "action" => "show"
            )
        );

        $children = $this->getChildren($row["id"]);

        if(count($children)){
            foreach($children as $child){

                $router = array_merge($router, $this->_createRoutes($child["id"], $slugPath."/".$child["slug"].""));

            }
        }
    }

    $routerConfig = new Zend_Config($router);

    Crcms_Config::setConfig("frontend_router", $routerConfig->toArray());

}
private function _createRoutes($id, $slugPath){
    $page = $this->getPage($id);

    $router["route_".$page["id"]] = array(
        "route" => $slugPath.".html",
        "defaults" => array(
            "pageId" => $page["id"],
            "locale" => $page["locale"],
            "module" => "frontend",
            "controller" => "page",
            "action" => "show"
        )
    );

    $children = $this->getChildren($page["id"]);

    if(count($children)){
        foreach($children as $child){
            $router = array_merge($router, $this->_createRoutes($child["id"], $slugPath."/".$child["slug"].""));
        }
    }

    return $router;
}

Так что теперь все в базе данных.В моем бустрапе я загружаю:

    protected function _initPostFrontController(){
    $this->bootstrap('frontController');

    $front = $this->getResource("FrontController");

    $frontendRouterConfig = new Zend_Config(Crcms_Config::getConfig("frontend_router"));

    $router = $front->getRouter();
    $router->addConfig($frontendRouterConfig);

    $front
        ->setParam("prefixDefaultModule", true)
        ->registerPlugin(new Global_Setup())
        ->registerPlugin(new Global_Auth())
        ->registerPlugin(new Global_Translation())
        ->registerPlugin(new Global_LayoutLoader());
}

Это мой Global_Setup:

class Global_Setup extends Zend_Controller_Plugin_Abstract {
public function preDispatch (Zend_Controller_Request_Abstract $request){

    $front = Zend_Controller_Front::getInstance();

    $errorHandler = $front->getPlugin("Zend_Controller_Plugin_ErrorHandler");
    $errorHandler->setErrorHandlerModule("frontend");

    $layout = Zend_Layout::getMvcInstance();
    $view = $layout->getView();

    switch($request->getModuleName()){
        case "admin":
            $session = new Zend_Session_Namespace("Crcms_Admin");

            $locale = Zend_Registry::get("Zend_Locale");
            $view->doctype("HTML5");        
            $view->headTitle(Zend_Registry::get("Zend_Config")->system->about->software);
            $view->headTitle()->setSeparator(" | ");
            $view->headTitle(Crcms_Config::getConfig("site_name"));
            $view->headLink()->headLink(array(
                "rel" => "shortcut icon",
                "href" => Zend_Registry::get("Zend_Config")->system->paths->http->publib."/images/favicon.ico"), "PREPEND");    
        break;
        default:
            $session = new Zend_Session_Namespace("Crcms_Frontend");

            if(!$session->locale){
                $session->locale = Crcms_Config::getConfig("locale_default");
            }

            $navigation = new Zend_Navigation(new Zend_Config(Crcms_Config::getConfig("navigation_".$session->locale)));
            $view->navigation()->setContainer($navigation);

        break;
    }

}

}

Так что в принципе все в порядке.LayoutLoader выбирает путь к макету по умолчанию и макет на основе admin / frontend.

В любом случае.В моем макете интерфейса у меня есть это:

<div id="menu"><?= $this->navigation()->menu(); ?></div>
<div id="breadcrumb"><?= $this->navigation()->breadcrumbs(); ?></div>
<div id="content"><?= $this->layout()->content; ?></div>

Меню создает нормально.Все уровни супер (Y).но ВСЕ - это класс = "активный" !!! и readcrumb всегда показывает самый глубокий элемент .

Выбор страницы работает отлично!Параметр pageId передается правильно, и маршрутизатор работает.Навигация только запуталась.

Некоторые картинки, чтобы дать вам идею:

Сторона администратора: - http://grab.by/6d67

Сторона интерфейса:

Так, как видно из фотографий, изменения URL- меняется и содержание.Так что роутер должен работать.

Все просто "активно": http://grab.by/6d6j

Я знаю, что здесь скопировал много информации, но, пожалуйста, помогите мне.Я как 20 часов работал над этой проблемой - без помощи решения.

Kinda исправил это .Я не думаю, что это «правильный путь», но тем не менее - он сейчас работает.Я прокомментировал контроллер / действие / модуль из навигации (ничего не изменилось в маршрутах).Добавлен "id" => "page -". $ Page ["id"].

Теперь в моем Global_Setup я сделал что-то вроде этого ->

$navigation = new Zend_Navigation(new Zend_Config(Crcms_Config::getConfig("navigation_".$session->locale)));
$navigation->findBy("id", "page-".$request->getParam("pageId"))
->setActive(true);

1 Ответ

4 голосов
/ 03 сентября 2010

Это что-то вроде предположения, так как сложно разобраться, просто взглянув на код.

Когда вы создаете свои маршруты, вы устанавливаете идентификатор страницы:

$router["route_".$row["id"]] = array(
    "route" => $slugPath.".html",
    "defaults" => array(
        "pageId" => $row["id"],
        "locale" => $row["locale"],
        "module" => "frontend",
        "controller" => "page",
        "action" => "show"
    )
);

Предположительно, это уникальный идентификатор, который вы используете в своем контроллере для определения, какая страница была запрошена?

Zend Navigation вызывает метод isActive () на каждой странице, чтобы определить, какой из них выделить. Для страниц Mvc то, что это делает, сравнивает заданные вами параметры маршрута (контроллер, модуль, действие и другие параметры) с параметрами в объекте запроса. В вашем случае все страницы указывают на одно и то же действие, и вы не дали Zend Navigation идентификатор страницы, поэтому все, что он делает, сравнивает модуль / контроллер / действие с модулем / контроллером / действием в запросе, который всегда будет соответствовать .

Если я прав, все, что вам нужно сделать, это добавить pageId к созданному вами навигационному объекту, поэтому в цикле в вашем первом примере кода:

$navigation[$row["id"]] = array(
    "label" => $row["name"],
    "module" => "frontend",
    "controller" => "page",
    "action" => "show",
    "route" => "route_".$row["id"],
    "params" => array("pageId" => $row["id"]), // this line is new!
    "visible" => (boolean) $row["active"],
    "lastmod" => ($row["modified"] ? $row["modified"] : $row["created"])
);

Если это не сработает, я надеюсь, что оно, по крайней мере, укажет вам правильное направление. Я думаю, что именно в этом заключается метод isActive (), поэтому, если вы не против отладки некоторого кода Zend Framework (временно), найдите этот метод в Zend / Navigation / Page / Mvc.php и убедитесь, что он вызывается и посмотрим, сможете ли вы выяснить, в чем дело.

...