Flexible Menu as per backend user

I want to create a flexible menu as in wordpress, that is backend user decides what appears in the navigation bar. Like home, about us, contact and other details. Can someone help me in this matter. I am stucked here.

I would like to describe all possible approaches to solving this problem, but unfortunately I don’t have time for it. But I’m going to present them in the nutshell and if you decide for one approach I’ll write more details about it.

You have following possibities:

  • declaring possible URLs on the side of PHP together with params mapping - this solution is good when your have fixed pool of possible websited that can occur in menu, and this pool is not going to change often (because with every new link you’ll have to modify your PHP code)

  • declare URL in database, handle mapping params on the PHP side - good when URLs pool is changing often and only some of them will require additional params (if you handle custom webpage content not by params, but by session for instance), also not so hard to design as you won’t need generic solution for params binding - just handle params in huge switch-case statement with case for every parameterized URL

  • declare both URLs and mapping parameters in DB - most elastic solution, but designing how to bing params with urls can be tricky - good when you can have a lot URls, and more will come in future, and many of them have parameters inside.

Can you give me some coding hints ? I desparately want to make my menu flexible.

In Controller class create an attribute called $menu. This attribute is array of arrays, which enables you to create random menu, with lot of submenus (you can create tree like menus)




public $menu = array(

	array(

		'icon'=>'fa fa-home',//I ussually define icon for every menu item, and this is a class from the font-awesome library.

		'url'=>$this->createUrl("site/home"),//Define URL for menu element

		'text'=>'Home'//Text which will appear on the website

		'menu'=>null//Submenu for this item

	),

	array(

		'icon'=>'fa fa-plus',

		'url'=>$this->createUrl("user/home"),

		'text'=>'Users'

		'menu'=>array(//example of submenu

			array(

				'icon'=>'fa fa-plus',

				'url'=>$this->createUrl("user/new"),

				'text'=>'New user'

				'menu'=>null

			),

			array(

				'icon'=>'fa fa-pencil',

				'url'=>$this->createUrl("user/update"),

				'text'=>'Edit user'

				'menu'=>null

			),

		)

	),

	array(

		'icon'=>'fa fa-home',

		'url'=>$this->createUrl("site/home"),

		'text'=>'Home'

		'menu'=>null

	),

);



In the controller’s init function, or in any controller method or view file you can add more elements in the $menu attribute using the following code




public function init(){

	array_push($this->menu, array(

		'icon'=>'fa fa-info',

		'url'=>$this->createUrl("site/aboutus"),

		'text'=>'About us'

		'menu'=>null

	));

}

So in the init function you can make a call to the DB, and fetch user defined menu.

To print menu, you can use recursion. Here is example of it:




public function printMenu($menu){

	foreach($menu as $m):

		echo '<li> <a href="'.$m['url'].'"> <i class=""></i>'.$m['text'].'</a>' //Print li element and inside li print <a> tag and <i> if you use Fontawesome 

		if(isset($m['menu'])){

			else echo '<ul>';

			$this->printMenu($m['menu']);//Reursion

			echo '</ul> </li>'

		}

		else echo '</li>'

	endforeach;

}

In your view file, you can print this menu using following code:


$this->printMenu($this->menu);

Hope I helped.