dongyou2635 2010-09-02 21:50
浏览 42
已采纳

Zend Navigation和Zend Router问题 - 找不到正确的活动页面

Okay. I'm building a CMS with Zend. It isn't as simple as it looked but still — the best solution for me. I have a tree system with ID and PARENT, PARENT marks under which page the child resides. Anyway. Simple stuff.

Every time a page is created or sorted Nav & Routes are regenerated.

I'll copy the whole Admin_Pages_Model code for creating Navigation and Routes here.

Navigation is created here: (I think that module/controller/action information isn't needed because it is loaded from router)

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

In the end - before saving navigation to database it calls $this->createRoutes(); So heres the code:

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

So now everything is database. In my boostrap I load:

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

This is my 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;
    }

}

}

So basically everything is Okay. The LayoutLoader selects the default layout path and the layout based on admin/frontend.

Anyway. In my frontend layout I have this :

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

The menu creates fine. All levels are super (Y). but EVERYTHING is class="active"!!! and readcrumb always shows the most deepest element.

The page selection works fine! The param pageId is passed right and the router works. Navigation is messed up only.

Some pics to give you the idea:

The admin side: - http://grab.by/6d67

The frontend side:

So as seen from the pictures URL changes - content changes also. So router must work.

Everything is just "active": http://grab.by/6d6j

I know that I've pasted alot of info here but please help me. I've like worked 20+ hours on this problem — no solution help.

Kinda fixed it. I don't think it's the "right way" but still - its now working. I commented controller/action/module out from the navigation thing (nothing has changed in Routes). Added a "id" => "page-".$page["id"].

Now in my Global_Setup I did something like this ->

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

1条回答 默认 最新

  • doumi1852 2010-09-02 23:15
    关注

    This is something of a guess, as it's hard to work this out just by looking at the code.

    When you are building up your routes, you're setting a pageId:

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

    Presumably this is the unique identifier you use in your controller to work out which page was requested?

    Zend Navigation calls the isActive() method on each page to work out which one to highlight. For Mvc pages what this does is compare the route params you've supplied (controller, module, action and other params) to the params in the request object. In your case, all of the pages point at the same action, and you haven't given Zend Navigation the pageId so all it's doing is comparing module/controller/action to the module/controller/action in the request, which will always match.

    If I'm right, all you need to do is add the pageId to the navigation object you build up, so in the loop in your first code sample:

    $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"])
    );
    

    If this doesn't work, I hope it will at least point you in the right direction. I do think the isActive() method is where the problem lies, so if you don't mind debugging some Zend Framework code (temporarily), find that method in Zend/Navigation/Page/Mvc.php, verify that it is being called, and see if you can figure out where it's going wrong.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 在获取boss直聘的聊天的时候只能获取到前40条聊天数据
  • ¥20 关于URL获取的参数,无法执行二选一查询
  • ¥15 液位控制,当液位超过高限时常开触点59闭合,直到液位低于低限时,断开
  • ¥15 marlin编译错误,如何解决?
  • ¥15 有偿四位数,节约算法和扫描算法
  • ¥15 VUE项目怎么运行,系统打不开
  • ¥50 pointpillars等目标检测算法怎么融合注意力机制
  • ¥20 Vs code Mac系统 PHP Debug调试环境配置
  • ¥60 大一项目课,微信小程序
  • ¥15 求视频摘要youtube和ovp数据集