Help : How to Load Menu from Database

hii all…

this is my first time using framework since i learn php 2 years ago.

This is the current menu (statis menu with array) :

this file is in protected\views\layouts\main.php


$this->widget('zii.widgets.CMenu',array(

		'items'=>array(

			array('label'=>'Home', 'url'=>array('/site/index')),

			array('label'=>'Our Vision', 'url'=>array('/site/page', 'view'=>'vision')),

			array('label'=>'Our Mission', 'url'=>array('/site/page', 'view'=>'mission')),

			array('label'=>'Our Activities', 'url'=>array('/site/page', 'view'=>'activity'))

			),

		));

Now,I want to have dynamic menu i load from database

this the sql table menu schema


CREATE TABLE [t_menu] (

[id] INTEGER  PRIMARY KEY AUTOINCREMENT NOT NULL,

[label] VARCHAR(128)  NULL,

[view_page] VARCHAR(128)  NULL,

[url] VARCHAR(128)  NULL,

[description] TEXT  NULL,

[status] INTEGER  NULL,

[position] INTEGER  NULL

)

i have already create this table, CRUD & MODEL and insert some data to.

So how i load this menu table data from sql, which file i must change and Add?

sorry i completely idiot. :(

thank a lot for your reply & spare time.

It will be a good idea to create a class extending CMenu and rewrite it’s init method at follows:




class ActiveMenu extends CMenu

{

    public function init()

    {

        MenuModel::model()->findAll();

        

        // Here you assign $this->items property in a loop...


        parent::init();

    }

}



And then just call $this->widget(‘application.components.ActiveMenu’) without “items” param.

thanks a lot for your reply [color="#9932CC"]#andy_s[/color].

Sorry i still confuse, which file i must put this class code "class ActiveMenu extends CMenu"? in the models folder, controllers folder, or just create one?

and how to loop in YII?

sorry to ask u this stupid guestion.

and how i can cofigurate this sql query condition, as u know there is status in the table menu for active or not active menu?

once more, thank a lot f u reply & i count on u. :)

Create a new file under protected/components directory and name it "ActiveMenu.php".

It’s contents:




Yii::import('zii.widgets.CMenu', true);


class ActiveMenu extends CMenu

{

    public function init()

    {

        // Here we define query conditions.

        $criteria = new CDbCriteria;

        $criteria->condition = '`status` = 1';

        $criteria->order = '`position` ASC';


        $items = MenuModel::model()->findAll($criteria);


        foreach ($items as $item)

            $this->items[] = array('label'=>$item->label, 'url'=>$item->url);

    }

}



MenuModel is a CActiveRecord you created.

Yes it works!! ;D

Advanced member is Awesome after all.

thanks a lot [color="#9932CC"]#andy_s[/color].

so this is how to retreive data from database and display it.

i think this some advantage of me using YII, he hee…

may we be best friend [color="#9932CC"]#andy_s[/color] ? :-*

You are welcome. And I hope all yii members are friends ;)

Hay Guys… I very NewBie… How if I want to set a sub menu using ActiveMenu, with mouseOver?.. base on a 8) topic above…

Is there someone who can help me?

There is this extension.

I have never used, so I cannot help you more, sorry!

Haah!. this is my 1st post a long long time ago when i’m still newbie(well, i am still newbie now) and that [color="#8B0000"]andy[/color] guy teach me a lot.

#Moh Badrullami : just use extension JQuerySlideTopMenu, and install it(very easy)

i have try another extension menu. but i think this is the best.

the bad is, the cointainer menu cannot be centered. only float left or right.

no big deal eh… B)

Thanks for your sugestion… I will try with JQuerySlideTopMenu…

Thanks to Andy, that idea of extending the CMenu for an database generated menu is very good! :)

good morning!

I have a problem with the code…

my situation is this:


CREATE TABLE IF NOT EXISTS `tbl_content` (

  `id` int(11) NOT NULL AUTO_INCREMENT,

  `varname` varchar(50) COLLATE utf8_spanish_ci NOT NULL,

  `titulo` varchar(255) COLLATE utf8_spanish_ci NOT NULL,

  `ruta` varchar(255) COLLATE utf8_spanish_ci NOT NULL,

  `permisos` int(3) NOT NULL,

  `showmenu` int(1) NOT NULL,

  `padre` int(11) NOT NULL,

  `content` text COLLATE utf8_spanish_ci NOT NULL,

  PRIMARY KEY (`id`)

)

ActiveMenu.php


<?php




Yii::import('zii.widgets.CMenu', true);


class ActiveMenu extends CMenu

{

    public function init()

    {

        // Here we define query conditions.

        $criteria = new CDbCriteria;

        $criteria->condition = '`showmenu` = 1';

        //$criteria->order = '`position` ASC';


        $items = Content::model()->findAll($criteria);


        foreach ($items as $item)

            $this->items[] = array('label'=>$item->titulo, 'url'=>$item->ruta);

    }

}

and main.php


<div id="mainmenu">

		<?php 

			


		$this->widget('zii.widgets.CMenu',array(

			'items'=>array(

				array('label'=>'Home', 'url'=>array('/site/index')),

				//define si es visible con usuario registrado

				array('label'=>'Contenido privado', 'url'=>array('/site/page', 'view'=>'about'),'visible'=>!Yii::app()->user->isGuest),

				array('label'=>'Contact', 'url'=>array('/site/contact')),	


				//array('label'=>'Login', 'url'=>array('/site/login'), 'visible'=>Yii::app()->user->isGuest),

				//array('label'=>'Logout ('.Yii::app()->user->name.')', 'url'=>array('/site/logout'), 'visible'=>!Yii::app()->user->isGuest)

				

				array('url'=>Yii::app()->getModule('user')->loginUrl, 'label'=>Yii::app()->getModule('user')->t("Login"), 'visible'=>Yii::app()->user->isGuest),

				array('url'=>Yii::app()->getModule('user')->registrationUrl, 'label'=>Yii::app()->getModule('user')->t("Register"), 'visible'=>Yii::app()->user->isGuest),

				array('url'=>Yii::app()->getModule('user')->profileUrl, 'label'=>Yii::app()->getModule('user')->t("Profile"), 'visible'=>!Yii::app()->user->isGuest),

				array('url'=>Yii::app()->getModule('user')->logoutUrl, 'label'=>Yii::app()->getModule('user')->t("Logout").' ('.Yii::app()->user->name.')', 'visible'=>!Yii::app()->user->isGuest)

				

			),

		)); 


		


		

		//para realizar la llamada $this->widget('application.components.ActiveMenu') sin "items" .

		$this->widget('application.components.ActiveMenu');




		?>

	</div><!-- mainmenu -->

this gives an error:


PHP notice


Undefined index: active


/var/www/yii/framework/zii/widgets/CMenu.php(190)


178      * Recursively renders the menu items.

179      * @param array $items the menu items to be rendered recursively

180      */

181     protected function renderMenuRecursive($items)

182     {

183         $count=0;

184         $n=count($items);

185         foreach($items as $item)

186         {

187             $count++;

188             $options=isset($item['itemOptions']) ? $item['itemOptions'] : array();

189             $class=array();

190             if($item['active'] && $this->activeCssClass!='')

191                 $class[]=$this->activeCssClass;

192             if($count===1 && $this->firstItemCssClass!==null)

193                 $class[]=$this->firstItemCssClass;

194             if($count===$n && $this->lastItemCssClass!==null)

195                 $class[]=$this->lastItemCssClass;

196             if($this->itemCssClass!==null)

197                 $class[]=$this->itemCssClass;

198             if($class!==array())

199             {

200                 if(empty($options['class']))

201                     $options['class']=implode(' ',$class);

202                 else


Stack Trace

#0 	

+

 /var/www/yii/framework/zii/widgets/CMenu.php(172): CMenu->renderMenuRecursive(array(array("label" => "Noticiones", "url" => "/site/page"), array("label" => "Ofertones", "url" => "/site/page")))

#1 	

+

 /var/www/yii/framework/zii/widgets/CMenu.php(159): CMenu->renderMenu(array(array("label" => "Noticiones", "url" => "/site/page"), array("label" => "Ofertones", "url" => "/site/page")))

#2 	

+

 /var/www/yii/framework/web/CBaseController.php(174): CMenu->run() 

.............

.........

.....

..

I can not see because it gives this error.

Anyone can help me?

thank you very much!!

I’m so lost :huh: :blink:

Sorry, I just found a little "bug" in my example:




Yii::import('zii.widgets.CMenu', true);


class ActiveMenu extends CMenu

{

    public function init()

    {

        // Here we define query conditions.

        $criteria = new CDbCriteria;

        $criteria->condition = '`status` = 1';

        $criteria->order = '`position` ASC';


        $items = MenuModel::model()->findAll($criteria);


        foreach ($items as $item)

            $this->items[] = array('label'=>$item->label, 'url'=>$item->url);

        

        parent::init();

    }

}



parent::init() is a must (it is present in the very first example).

thank you very much!!!!!!!!!!!!!!!

the code works perfect ;) ;D

can u please explain how u used the code and the necessary changes to be made within the view and other files…

it will help a lot of people like me…

thanks…

There is an existing tutorial (fairly recent) on building a Cmenu with one or more menus stored in a database. It uses the adjacency list model (parent_id) to handle the nested menu levels recursively. This is a two table solution with a menu and menu_item table, and it probably makes better sense if your menus need to be translated.

It would probably make better sense to take the above and refactor the code into a portlet (CPortlet) which is extended from CWidget. Then the widget code becomes reusable for any main layout or theme layout by inserting the code in a menu layout region (<div>…</div>)if horizontal or in a left or right column if vertical, resulting in less code in your layouts. Portlets are discussed in the manual and an older XPortlet (predecessor to CPortlet) tutorial from Quiang or Wei exists to demonstrate how to integrate a login portlet into the blog tutorial. If you work in an environment where a separate template (theme) designer is used and you need to minimize code in your theme, portlets are a good solution for this.

Great code friend!

Just wanna ask if you can help me to know how to insert/put/get a variable into the function, like:




$criteria->condition = '`status` = 1 AND `system` ='.$variable;



Or try to re-edit the same function into a new one.

Thank you so much!

ActiveMenu.php

<?php

Yii::import(‘zii.widgets.CMenu’, true);

class ActiveMenu extends CMenu

{

public function init()


{


    // Here we define query conditions.


    &#036;criteria = new CDbCriteria;


    &#036;criteria-&gt;condition = '`status` = 1  and Parent_id=0';


    &#036;criteria-&gt;order = '`position` ASC';





    &#036;items = TMenu::model()-&gt;findAll(&#036;criteria);


	


    foreach (&#036;items as &#036;item )


	{


		/*&#036;child=&quot;Select label,url from t_menu where Parent_id='&#036;item-&gt;id'&quot;;


		&#036;childs=Yii::app()-&gt;db-&gt;createCommand(&#036;child)-&gt;queryAll();*/


		//&#036;child=TMenu::model()-&gt;findAll(&quot;Parent_id=&#036;item-&gt;id&quot;);


		//echo &#036;child[0]['label'];


		/*&#036;this-&gt;items[] = array('label'=&gt;&#036;item-&gt;label, 'url'=&gt;&#036;item-&gt;url,'items'=&gt;array(array('label'=&gt;'arpit', 'url'=&gt;'#')*/));


		


	}


	//foreach(&#036;child as &#036;childs)


        


    parent::init();


}

}

?>

Layout main.php

<div id="menu">

	&lt;?php &#036;this-&gt;widget('application.components.ActiveMenu');?&gt;


&lt;/div&gt;

This code work perfactly for one level menu for database.

but i want to make multi level menu from database so plz help me to make it.

thanks

Arpit sharma


// components/menuActive.php

public function cmdQuery($sql)

    {

        return YII::app()->db->createCommand($sql);

    }

public function getMenuParent($menuId)

    {

        $sqlMenuParent = "select * from tbl_menus where menu_level=".$menuId;

        return  $this->cmdQuery($sqlMenuParent)->queryAll();

    }

public function buildMenu($menuId,$order)

    {

        $menus = $this->getMenuParent($menuId);

        $order++;

        $html = "";

        if($menus)

        {

            $html.="<ul class='ul_menutop".$order."'>";

            foreach ($menus as $menu) {

               $html.="<li class='li_menutop".$order."'>";

               $html.="<a href='".$menu["menu_id"]."'>".$menu["menu_name"]."</a>";//href not loop <img src='http://www.yiiframework.com/forum/public/style_emoticons/default/sad.gif' class='bbc_emoticon' alt=':(' />

               $html.= $this->buildMenu($menu['menu_id'], $order) ;

               $html.="</li>";

            }

            $html.="</ul>";

        }

        

        return $html;

    }

public function init()

    {

        echo $this->buildMenu(0,0);

        parent::init();

    }




// view/layouts/main.php

$this->widget('application.components.ActiveMenu') ;




Hi it works for main menu. I want to create custom mainmenu and submenu from database. Please help me.

I tried the following code but i am not satisfied.


<?php 

Yii::import('zii.widgets.CMenu', true);


class ActiveMenu extends CMenu

{

	


			public function buildMenu()

			    {

			        $menus = Category::model()->findAll();

			        $html = "";

			       

			        	

	        			$html.="<ul id='yw2' class='sf-js-enabled'>";

			        	$html.='<li ><a href="/test/index.php/post/index">Tutorials</a></li>';

			        	$html.="<li><a href='/test/index.php/post/archives'>Articles</a></li>";

			        	$html.="<li class=''><a href='#'>Category</a>";

			        	$html.="<ul style='display: none; visibility: hidden;' class='sf-js-enabled'>";

			        	foreach ($menus as $menu) {

			        		$html.="<li><a href='/test/index.php/post/category/id/1'>".$menu->CategoryName."</a></li>";

			        	}

			        	$html.="</ul>";

			        	

			        	$html.="</ul>";

			        	

			        

			        

			        return $html;

			    }

			public function init()

			    {

			        echo $this->buildMenu();

			        parent::init();

			    }

	


}

?>