{"id":188,"date":"2014-09-26T05:21:55","date_gmt":"2014-09-26T05:21:55","guid":{"rendered":"http:\/\/localhost\/syllogic\/wp\/?p=188"},"modified":"2024-02-02T12:22:27","modified_gmt":"2024-02-02T12:22:27","slug":"dynamic-menus","status":"publish","type":"post","link":"http:\/\/localhost:10008\/dynamic-menus\/","title":{"rendered":"Dynamic Menus"},"content":{"rendered":"\n

There are many good tutorials to build custom menus for logged in\/logged out users, see also our own post on the ajax login menu<\/a>.  There are more complex approaches in order to customise the individual menu items<\/a> using a the wordpress Walker class<\/a>.  An excellent review of a custom walker<\/a> can be found on the WordPress StackExchange<\/a>.<\/p>\n\n\n\n

However, I was looking to actually add menu items dynamically depending on the state of the site.  In this case, we have a client, a research centre at a university who asked us to redevelop their site as a portal of all their conference sites.  We created a WordPress MU portal which we customised to enable them to create new conference sites based on a template site that is pre-configured, enabling registration forms, abstract submission forms, payment gateways to be created for each new conference at the press of a button in the Dashboard.<\/p>\n\n\n\n

One of the challenges was to dynamically add new conference sites to the main site menu as when they are created.  Furthermore, the conference menu has a Past sub-menu in which old conferences need to be listed.<\/p>\n\n\n\n

I decided to use the Walker extension solution by adding a little customisation. \u00a0I created a new class, AddExtraMenuItems_Walker<\/code>, which extends the WordPress core \u00a0Walker_Nav_Menu class<\/a>.<\/p>\n\n\n\n

Full code<\/summary>\n
\/**\n * Walker Navigation Menu class to insert dynamic content into menus\n * use the constructor at creation to pass the dynamic menu content\n *\/\nclass AddExtraMenuItems_Walker extends Walker_Nav_Menu{\n public $insertMenus = array();\n protected $nextMenu = '';\n \/**\n * Constructor takes an array\n *\n *@param array $menu_insert an array of key=>value pairs with\n *each key being the parent menu underwhich to insert the extra menu items,\n *and the value being an array containing menu items as array values of the following form,\n *array( 'url' => permalink for the menu item (default ='#'),\n * 'title' => menu title (default = '<i> Missing Title<\/i>'),\n * 'id' => css id value for the <li> term (default = ''),\n * 'class' => ',' delimited string of css classes for the <li> term (default='') ), each\n *menu will be wrapped in <a> tags that will open in a new window. \n *\/\n function __construct($menu_insert = array()) {\n   $this->insertMenus = $menu_insert;\n } \n \n function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {\n   $menu_item = apply_filters( 'the_title', $item->title, $item->ID );\n   if(array_key_exists($menu_item,$this->insertMenus)){\n     \/\/check if to be listed or inserted as sub-menu\n     $menuTree = $this->insertMenus[$menu_item];\n     $subMenu = ! empty($menuTree['sub-menu']) ? true:false;\n     \/*\n     *if this is a sub-mneu insert, ;let's make sure our current\n     *menu-item has the required class to identify it as such\n     *\/\n     if($subMenu && ! empty($menuTree['class'])) $item->classes[]=$menuTree['class'];\n       \/\/call parent function\n       parent::start_el($output, $item, $depth, $args);\n       \/\/now if we have a sub-menu tree we need to insert it here\n       if($subMenu){\n          $classes = ! empty($menuTree['ul-class']) ? ' class=\"'.$menuTree['class'].'\"' : ' class=\"sub-menu\"';\n          $output .= '<ul'.$class.'>';\n          foreach($menuTree['sub-menu'] as $menu_item){\n            $classes = ! empty($menu_item['class']) ? '\" class=\"'.$menu_item['class'].'\"' : '';\n            $id = ! empty($menu_item['id']) ? ' id=\"'.$menu_item['id'].'\"' : '';\n            $url =! empty($menu_item['url']) ? $menu_item['url'] : '#';\n             $title=! empty($menu_item['title']) ? $menu_item['title'] : '<i>Missing Title<\/i>';\n             $output .= '<li'.$id.$classes.'><a href=\"'.$url.'\" target=\"_blank\">'.$title.'<\/a><\/li>';\n          }\n          $output .= '<\/ul>'; \/\/let's close our sub-menu\n       }else $this->nextMenu = $menuTree; \/\/else we pass the menu items to be inserted as list items in the start call\n   }else parent::start_el($output, $item, $depth, $arg);\n }\n \n function start_lvl( &$output, $depth = 0, $args = array()) {\n   parent::start_lvl($output, $depth, $args);\n   if($this->nextMenu){\n     foreach($this->nextMenu as $menu_item){\n       $classes = ! empty($menu_item['class']) ? '\" class=\"'.$menu_item['class'].'\"' : '';\n       $id = ! empty($menu_item['id']) ? ' id=\"'.$menu_item['id'].'\"' : '';\n       $url =! empty($menu_item['url']) ? $menu_item['url'] : '#';\n       $title=! empty($menu_item['title']) ? $menu_item['title'] : '<i>Missing Title<\/i>';\n       $output .= '<li'.$id.$classes.'><a href=\"'.$url.'\" target=\"_blank\">'.$title.'<\/a><\/li>';\n     }\n   $this->nextMenu=''; \/\/reset\n   }\n }\n \n}<\/code><\/pre>\n<\/details>\n\n\n\n

So the Walker class is simply called in the wordpress function to display a menu structure,<\/p>\n\n\n\n

wp_nav_menu( array('walker'=> new AddExtraMenuItems_Walker($extra_menu), 'theme_location' => 'primary-menu', 'container' => '', 'fallback_cb' => '', 'menu_class' => 'my-menu-class', 'menu_id' => 'top-menu', 'echo' => false ) );<\/code><\/pre>\n\n\n\n

Remains to define the $extra_menu array arguments that are passed to the walker in order to insert it into the right menu. Here is an example. It assumes that there is a primary menu created in the Dashboard with the top level menu item ‘Conferences’ and a sub-item below this called ‘Past’,<\/p>\n\n\n\n

$extra_menu = array(\n 'Conferences'=>array(array('title'=>'ISOl 2015',\n                               'url' => 'http:\/\/syllogic.asia\/2015\/',\n                               'id' => 'menu_item_isol_2',\n                               'class'=> 'menu-item menu-item-type-custom menu-item-object-custom'),\n                         array('title'=>'ISOl Chicago',\n                               'url' => 'http:\/\/syllogic.asia\/2015\/',\n                               'id' => 'menu_item_isol_3',\n                               'class'=> 'menu-item menu-item-type-custom menu-item-object-custom')),\n 'Past'=>array('ul-class'=>'sub-menu',\n                  'class'=>'menu-item-has-children left-sub-menu',\n                  'sub-menu'=>array(array('title'=>'ISOl 2015',\n                                             'url' => 'http:\/\/syllogic.asia\/2015\/',\n                                             'id' => 'menu_item_isol_2',\n                                             'class'=> 'menu-item menu-item-type-custom menu-item-object-custom'),\n                                       array('title'=>'ISOl Chicago',\n                                             'url' => 'http:\/\/syllogic.asia\/2015\/',\n                                             'id' => 'menu_item_isol_3',\n                                             'class'=> 'menu-item menu-item-type-custom menu-item-object-custom'))));<\/code><\/pre>\n\n\n\n

There is 2 type of menu being inserted here, the first one under ‘Conferences’ menu item, are 2 extra sub-item which are simply listed within the existing sub-menu list of ‘Conferences’.
\nThe second set of menu is an entire sub-menu structure being replaced instead of an existing menu-item. In other words, ‘Past’ is a sub-item of top menu item ‘Conferences’. As such ‘Past’ does not have any children. This 2nd set of dynamic menu are placed below the ‘Past’, making it into a sub-menu.<\/p>\n\n\n\n

Menu structures are dined as an array with,<\/p>\n\n\n\n

array('title'=>the text of the menu item<\/em>,\n      'url' => the permalink for the menu<\/em>,\n      'id' => a css id for the <li> element<\/em>,\n      'class'=> css classes for the <li> element<\/em>)<\/code><\/pre>\n\n\n\n

To add an entire sub-menu to a given item, you need to specify some extra arguments, namely the classes that changes an item into a sub-menu (on hover the sub-menu will appear) if you are using pure CSS for your menus. This is done using the following structure,<\/p>\n\n\n\n

array('ul-class'=>the css class for the sub-menu <\/em>
    element<\/em>,\n 'class'=>the css class for the menu item that will change to a sub-menu structure<\/em>,\n 'sub-menu'=>array( sub-menu items as arrays, as defined above<\/em> )<\/ul><\/code><\/pre>\n\n\n\n

    That’s it. Feel free to comment, query, clarify below…<\/p>\n","protected":false},"excerpt":{"rendered":"

    There are many good tutorials to build custom menus for logged in\/logged out users, see also our own post on the ajax login menu.  There are more complex approaches in order to customise the individual menu items using a the wordpress Walker class.  An excellent review of a custom walker can be found on the […]<\/p>\n","protected":false},"author":2,"featured_media":343,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9,14],"tags":[16,17],"yoast_head":"\nDynamic Menus - Tiffin Consulting<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"http:\/\/localhost:10008\/dynamic-menus\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Dynamic Menus - Tiffin Consulting\" \/>\n<meta property=\"og:description\" content=\"There are many good tutorials to build custom menus for logged in\/logged out users, see also our own post on the ajax login menu.  There are more complex approaches in order to customise the individual menu items using a the wordpress Walker class.  An excellent review of a custom walker can be found on the […]\" \/>\n<meta property=\"og:url\" content=\"http:\/\/localhost:10008\/dynamic-menus\/\" \/>\n<meta property=\"og:site_name\" content=\"Tiffin Consulting\" \/>\n<meta property=\"article:published_time\" content=\"2014-09-26T05:21:55+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-02-02T12:22:27+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/localhost:10008\/wp-content\/uploads\/2014\/09\/keep-coding-and-keep-walking.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"933\" \/>\n\t<meta property=\"og:image:height\" content=\"576\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Aurovrata V.\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Aurovrata V.\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\n\t \"@context\": \"https:\/\/schema.org\",\n\t \"@graph\": [\n\t {\n\t \"@type\": \"Article\",\n\t \"@id\": \"http:\/\/localhost:10008\/dynamic-menus\/#article\",\n\t \"isPartOf\": {\n\t \"@id\": \"http:\/\/localhost:10008\/dynamic-menus\/\"\n\t },\n\t \"author\": {\n\t \"name\": \"Aurovrata V.\",\n\t \"@id\": \"http:\/\/localhost:10008\/#\/schema\/person\/361f7db128e2b6858c7deb2a43f85f99\"\n\t },\n\t \"headline\": \"Dynamic Menus\",\n\t \"datePublished\": \"2014-09-26T05:21:55+00:00\",\n\t \"dateModified\": \"2024-02-02T12:22:27+00:00\",\n\t \"mainEntityOfPage\": {\n\t \"@id\": \"http:\/\/localhost:10008\/dynamic-menus\/\"\n\t },\n\t \"wordCount\": 443,\n\t \"publisher\": {\n\t \"@id\": \"http:\/\/localhost:10008\/#\/schema\/person\/e7549052d5ca8cb5891c059c2424a9f6\"\n\t },\n\t \"keywords\": [\n\t \"menu\",\n\t \"walker\"\n\t ],\n\t \"articleSection\": [\n\t \"Menus\",\n\t \"Theme Reviews\"\n\t ],\n\t \"inLanguage\": \"en-US\"\n\t },\n\t {\n\t \"@type\": \"WebPage\",\n\t \"@id\": \"http:\/\/localhost:10008\/dynamic-menus\/\",\n\t \"url\": \"http:\/\/localhost:10008\/dynamic-menus\/\",\n\t \"name\": \"Dynamic Menus - Tiffin Consulting\",\n\t \"isPartOf\": {\n\t \"@id\": \"http:\/\/localhost:10008\/#website\"\n\t },\n\t \"datePublished\": \"2014-09-26T05:21:55+00:00\",\n\t \"dateModified\": \"2024-02-02T12:22:27+00:00\",\n\t \"breadcrumb\": {\n\t \"@id\": \"http:\/\/localhost:10008\/dynamic-menus\/#breadcrumb\"\n\t },\n\t \"inLanguage\": \"en-US\",\n\t \"potentialAction\": [\n\t {\n\t \"@type\": \"ReadAction\",\n\t \"target\": [\n\t \"http:\/\/localhost:10008\/dynamic-menus\/\"\n\t ]\n\t }\n\t ]\n\t },\n\t {\n\t \"@type\": \"BreadcrumbList\",\n\t \"@id\": \"http:\/\/localhost:10008\/dynamic-menus\/#breadcrumb\",\n\t \"itemListElement\": [\n\t {\n\t \"@type\": \"ListItem\",\n\t \"position\": 1,\n\t \"name\": \"Home\",\n\t \"item\": \"http:\/\/localhost:10008\/\"\n\t },\n\t {\n\t \"@type\": \"ListItem\",\n\t \"position\": 2,\n\t \"name\": \"Dynamic Menus\"\n\t }\n\t ]\n\t },\n\t {\n\t \"@type\": \"WebSite\",\n\t \"@id\": \"http:\/\/localhost:10008\/#website\",\n\t \"url\": \"http:\/\/localhost:10008\/\",\n\t \"name\": \"Tiffin Consulting\",\n\t \"description\": \"digital business transformation\",\n\t \"publisher\": {\n\t \"@id\": \"http:\/\/localhost:10008\/#\/schema\/person\/e7549052d5ca8cb5891c059c2424a9f6\"\n\t },\n\t \"potentialAction\": [\n\t {\n\t \"@type\": \"SearchAction\",\n\t \"target\": {\n\t \"@type\": \"EntryPoint\",\n\t \"urlTemplate\": \"http:\/\/localhost:10008\/?s={search_term_string}\"\n\t },\n\t \"query-input\": \"required name=search_term_string\"\n\t }\n\t ],\n\t \"inLanguage\": \"en-US\"\n\t },\n\t {\n\t \"@type\": [\n\t \"Person\",\n\t \"Organization\"\n\t ],\n\t \"@id\": \"http:\/\/localhost:10008\/#\/schema\/person\/e7549052d5ca8cb5891c059c2424a9f6\",\n\t \"name\": \"Aurovrata V.\",\n\t \"image\": {\n\t \"@type\": \"ImageObject\",\n\t \"inLanguage\": \"en-US\",\n\t \"@id\": \"http:\/\/localhost:10008\/#\/schema\/person\/image\/\",\n\t \"url\": \"http:\/\/localhost:10008\/wp-content\/uploads\/2024\/02\/tiffin-dabbawalla.png\",\n\t \"contentUrl\": \"http:\/\/localhost:10008\/wp-content\/uploads\/2024\/02\/tiffin-dabbawalla.png\",\n\t \"width\": 1060,\n\t \"height\": 644,\n\t \"caption\": \"Aurovrata V.\"\n\t },\n\t \"logo\": {\n\t \"@id\": \"http:\/\/localhost:10008\/#\/schema\/person\/image\/\"\n\t },\n\t \"sameAs\": [\n\t \"http:\/\/localhost:10008\"\n\t ]\n\t },\n\t {\n\t \"@type\": \"Person\",\n\t \"@id\": \"http:\/\/localhost:10008\/#\/schema\/person\/361f7db128e2b6858c7deb2a43f85f99\",\n\t \"name\": \"Aurovrata V.\",\n\t \"image\": {\n\t \"@type\": \"ImageObject\",\n\t \"inLanguage\": \"en-US\",\n\t \"@id\": \"http:\/\/localhost:10008\/#\/schema\/person\/image\/\",\n\t \"url\": \"http:\/\/2.gravatar.com\/avatar\/?s=96&d=mm&r=g\",\n\t \"contentUrl\": \"http:\/\/2.gravatar.com\/avatar\/?s=96&d=mm&r=g\",\n\t \"caption\": \"Aurovrata V.\"\n\t },\n\t \"url\": \"http:\/\/localhost:10008\/author\/aurovrata\/\"\n\t }\n\t ]\n\t}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Dynamic Menus - Tiffin Consulting","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"http:\/\/localhost:10008\/dynamic-menus\/","og_locale":"en_US","og_type":"article","og_title":"Dynamic Menus - Tiffin Consulting","og_description":"There are many good tutorials to build custom menus for logged in\/logged out users, see also our own post on the ajax login menu.  There are more complex approaches in order to customise the individual menu items using a the wordpress Walker class.  An excellent review of a custom walker can be found on the […]","og_url":"http:\/\/localhost:10008\/dynamic-menus\/","og_site_name":"Tiffin Consulting","article_published_time":"2014-09-26T05:21:55+00:00","article_modified_time":"2024-02-02T12:22:27+00:00","og_image":[{"width":933,"height":576,"url":"http:\/\/localhost:10008\/wp-content\/uploads\/2014\/09\/keep-coding-and-keep-walking.jpg","type":"image\/jpeg"}],"author":"Aurovrata V.","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Aurovrata V.","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"http:\/\/localhost:10008\/dynamic-menus\/#article","isPartOf":{"@id":"http:\/\/localhost:10008\/dynamic-menus\/"},"author":{"name":"Aurovrata V.","@id":"http:\/\/localhost:10008\/#\/schema\/person\/361f7db128e2b6858c7deb2a43f85f99"},"headline":"Dynamic Menus","datePublished":"2014-09-26T05:21:55+00:00","dateModified":"2024-02-02T12:22:27+00:00","mainEntityOfPage":{"@id":"http:\/\/localhost:10008\/dynamic-menus\/"},"wordCount":443,"publisher":{"@id":"http:\/\/localhost:10008\/#\/schema\/person\/e7549052d5ca8cb5891c059c2424a9f6"},"keywords":["menu","walker"],"articleSection":["Menus","Theme Reviews"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"http:\/\/localhost:10008\/dynamic-menus\/","url":"http:\/\/localhost:10008\/dynamic-menus\/","name":"Dynamic Menus - Tiffin Consulting","isPartOf":{"@id":"http:\/\/localhost:10008\/#website"},"datePublished":"2014-09-26T05:21:55+00:00","dateModified":"2024-02-02T12:22:27+00:00","breadcrumb":{"@id":"http:\/\/localhost:10008\/dynamic-menus\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["http:\/\/localhost:10008\/dynamic-menus\/"]}]},{"@type":"BreadcrumbList","@id":"http:\/\/localhost:10008\/dynamic-menus\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"http:\/\/localhost:10008\/"},{"@type":"ListItem","position":2,"name":"Dynamic Menus"}]},{"@type":"WebSite","@id":"http:\/\/localhost:10008\/#website","url":"http:\/\/localhost:10008\/","name":"Tiffin Consulting","description":"digital business transformation","publisher":{"@id":"http:\/\/localhost:10008\/#\/schema\/person\/e7549052d5ca8cb5891c059c2424a9f6"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"http:\/\/localhost:10008\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"http:\/\/localhost:10008\/#\/schema\/person\/e7549052d5ca8cb5891c059c2424a9f6","name":"Aurovrata V.","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"http:\/\/localhost:10008\/#\/schema\/person\/image\/","url":"http:\/\/localhost:10008\/wp-content\/uploads\/2024\/02\/tiffin-dabbawalla.png","contentUrl":"http:\/\/localhost:10008\/wp-content\/uploads\/2024\/02\/tiffin-dabbawalla.png","width":1060,"height":644,"caption":"Aurovrata V."},"logo":{"@id":"http:\/\/localhost:10008\/#\/schema\/person\/image\/"},"sameAs":["http:\/\/localhost:10008"]},{"@type":"Person","@id":"http:\/\/localhost:10008\/#\/schema\/person\/361f7db128e2b6858c7deb2a43f85f99","name":"Aurovrata V.","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"http:\/\/localhost:10008\/#\/schema\/person\/image\/","url":"http:\/\/2.gravatar.com\/avatar\/?s=96&d=mm&r=g","contentUrl":"http:\/\/2.gravatar.com\/avatar\/?s=96&d=mm&r=g","caption":"Aurovrata V."},"url":"http:\/\/localhost:10008\/author\/aurovrata\/"}]}},"_links":{"self":[{"href":"http:\/\/localhost:10008\/wp-json\/wp\/v2\/posts\/188"}],"collection":[{"href":"http:\/\/localhost:10008\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/localhost:10008\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/localhost:10008\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/localhost:10008\/wp-json\/wp\/v2\/comments?post=188"}],"version-history":[{"count":2,"href":"http:\/\/localhost:10008\/wp-json\/wp\/v2\/posts\/188\/revisions"}],"predecessor-version":[{"id":342,"href":"http:\/\/localhost:10008\/wp-json\/wp\/v2\/posts\/188\/revisions\/342"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/localhost:10008\/wp-json\/wp\/v2\/media\/343"}],"wp:attachment":[{"href":"http:\/\/localhost:10008\/wp-json\/wp\/v2\/media?parent=188"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/localhost:10008\/wp-json\/wp\/v2\/categories?post=188"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/localhost:10008\/wp-json\/wp\/v2\/tags?post=188"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}