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