Whenever I render a menu item, for each of the menu item I found from the database, I use it to check its sub-menus.
My Controller rendering the menu item and recursive function to detect its sub-menus are as follows
public function renderAction()
{
$menu = $this -> _request -> getParam('menu');
$itemArray = $this -> getSubItems($menu);
$container = new Zend_Navigation($itemArray);
$this -> view -> navigation() -> setContainer($container);
}
private function getSubItems($menu, $parent = 0) {
$mapperMenuItem = new Apanel_Model_Mapper_MenuItem();
$menuItems = $mapperMenuItem -> getItemsByMenu($menu, $parent);
if(count($menuItems) > 0) {
$itemArray = array();
foreach($menuItems as $item) {
$label = $item -> label;
$uri = $this -> getSubItemUrl($item);
$subItems = $this -> getSubItems($menu, $item -> id);
if(count($subItems)) {
$tArray['pages'] = $subItems;
}
$tArray['label'] = $label;
$tArray['uri'] = $uri;
$itemArray[] = $tArray;
unset($tArray);
}
if(count($itemArray)) {
return $itemArray;
} else {
return null;
}
} else {
return null;
}
}
private function getSubItemUrl($item) {
if(!empty($item -> link)) {
$uri = $item -> link;
} else {
$pageMapper = new Apanel_Model_Mapper_Page();
$details = $pageMapper -> getPageDetails($item -> page_id);
$pageClass = "CMS_Content_Item_".ucwords($details['namespace']);
$page = new $pageClass($item -> page_id);
$title = str_replace(" ", "-", strtolower($details['name']));
$uri = $this -> view -> url(array(
"namespace" => $details['namespace'],
"title" => $title
),'page-view');
}
return $uri;
}
And function getItemsByMenu in MenuItem Mapper
public function getItemsByMenu($menuId, $parent = 0) {
$select = $this -> getDbTable() -> select();
$select -> where("menu_id = ?", $menuId)
-> where("parent = ?", $parent)
-> order("position");
$items = $this -> getDbTable() -> fetchAll($select);
if($items -> count() > 0) {
return $items;
} else {
return null;
}
}
I have about 4 different types of menu rendered in my app and I am noticing significant performance degradation in the execution. I often get Execution timeouts, the difference between the rendering time with the menus are about 35 sec and without are 22 sec approx. And this all in localhost. Is there any flaw in my recursion? What measure can I take to improve the performance of the code?
I can’t see anything in there that would explain 35 second execution time, unless you have 100,000s of items in your menus table with no indexes at all. Suggestions:
Make sure you have an index on the menu items table on:
menu_id, parent, position(that’s one index on three fields, with the fields in that order.I assume
getPageDetailsis doing another database query. Ideally you’d want to load these details when you load the menu items (by joining in the pages table), so you could then just pass the array of page data togetPageDetailsinstead of having to do an additional query per item.If that doesn’t give any miraculous improvements, try enabling the DB profiler so you can see whether it’s volume or speed of the database queries that is causing the issue.