Собственно набросал тут небольшой генератор многоуровневых меню на основе конфига, из плюшек возможность разграничивать права доступа к пунктам.
авось кому пригодится.
Писал в свободное от запары время, посему возможно где-то что-то не так, за правки и дополнения буду признателен.
Конфиг (app/config/menu.php)
Код:
<?php defined('SYSPATH') or die('No direct access allowed.');
/**
* User: mamahtehok
* Date: 14.08.12
* Time: 15:04
*
* Конфиг для генирации меню
*/
return array(
'demo' => array(
'menu_rule' => 'all',
'main' => array( //название пункта применяется для удобства навигации по конфигу
'menu_role' => 'all', //роль которой доступен пункт, распрастраняется на дочерние пункты
'ul_attr' => array(), //атребуты вышестоящего тега ul
'li_attr' => array(), //атребуты тега li
'attr' => array(), //аттребуты линка
'name' => 'Главная', //Отображаемео название пункта
'url' => URL::site(), //Урл для пункта
'level1' => array(
'name' => 'level1',
'level1.1' => array(
'name' => 'level1.1',
'level1.1.1' => array(
'name' => 'level1.1.1',
),
),
'level1.2' => array('name'=>'level1.2'),
),
'level2' => array(
'menu_role'=>'admin',
'name'=>'level2'
),
),
),
);
Контроллер (app/class/controllers/menu)
Код:
<?php defined('SYSPATH') or die('No direct access allowed.');
/**
* User: mamahtehok
* Date: 14.08.12
* Time: 15:19
*/
class Controller_Menu extends Controller
{
/* @var Config $config*/
protected $user;
protected $roleArr;
protected $config;
protected $next = true;
protected $view = 'menu';
public function before()
{
parent::before();
//Грузим конфиг в котором описанно меню
$this->config = Kohana::$config->load('menu');
if($this->user = Auth::instance()->get_user())
{
$this->role = $this->user->roles->find_all();
$this->roleArr = array();
foreach ($this->role as $role) {
$this->roleArr[] = $role->name;
}
$this->roleArr[] = 'all';
}
else
{
$this->roleArr[0] = 'all';
}
}
public function action_get()
{
$menuName = $this->request->param('id');
if($menu = $this->config->get($menuName))
{
if(!isset($menu['menu_role']) || $this->check_role($menu['menu_role']))
{
$view = View::factory($this->view)->bind('tree',$html);
$this->arrRecurs($menu,$html);
$this->response->body($view->render());
} else {
$this->response->body('Access deny');
}
} else {
$this->response->body('Don\'t load this menu');
}
}
public function after()
{
parent::after();
}
private function check_role($role)
{
if(in_array($role,$this->roleArr))
{
return true;
} else {
return false;
}
}
public function arrRecurs($array,&$html = '',&$level = 0,&$prevlevel = 1)
{
$level++;
$ul_attr = (isset($array['ul_attr'])) ? $array['ul_attr'] : array();
if($level > $prevlevel) $html .= '<ul '.HTML::attributes($ul_attr).'>'."\n";
$prevlevel = $level;
foreach ($array as $key => $value)
{
if(!$this->next) continue;
if( !preg_match('/attr/',$key) and is_array($value)){
$this->next = TRUE;
if (isset($link)) $html .= $this->viewrender($link,$render);
$this->arrRecurs($value,$html,$level,$prevlevel);
} else {
switch($key)
{
case 'menu_role':
$this->next = (!$this->check_role($value)) ? FALSE : TRUE;
break;
case 'url':
$link['url'] = $value;
break;
case 'name':
$link['name'] = $value;
break;
case 'attr':
$link['attr'] = $value;
break;
case 'li_attr':
$link['li_attr'] = $value;
break;
}
}
}
if (isset($link)) $html .= $this->viewrender($link,$render);
if($level < $prevlevel) $html .= '</ul>'."\n";
$level--;
}
private function viewrender(&$link,&$renderState = felse)
{
if(!$renderState)
{
$li_attr = (isset($link['li_attr'])) ? $link['li_attr'] : array();
$url = (isset($link['url'])) ? $link['url'] : '';
$name = (isset($link['name'])) ? $link['name'] : 'none';
$attr = (isset($link['attr'])) ? $link['attr'] : array();
$view = '<li'.HTML::attributes($li_attr).">\n".HTML::anchor($url,$name,$attr)."\n</li>";
$renderState = true;
return $view;
}
}
}
вьюшка (views/menu.php)
Код:
<?php defined('SYSPATH') or die('No direct access allowed.');
/**
* User: mamahtehok
* Date: 16.08.12
* Time: 16:12
*/
echo $tree
?>
Вызываем из другой вьюшки (или контроллера) следубщим образов
Код:
echo Request::factory('menu/get/<menu_name>')->execute()->body();
В примере моего конфига вызов из основной вьюшки
Код:
<?=echo Request::factory('menu/get/demo')->execute()->body()?>
на выходе получим
Вложение:
Снимок экрана 2012-08-16 в 18.42.03.png [ 9.17 КБ | Просмотров: 5406 ]
Код:
<ul >
<li>
<a href="/myv/myv">Главная</a>
</li><ul >
<li>
<a href="/myv/">level1</a>
</li><ul >
<li>
<a href="/myv/">level1.1</a>
</li><ul >
<li>
<a href="/myv/">level1.1.1</a>
</li></ul>
<li>
<a href="/myv/">level1.2</a>
</li></ul>
</ul>
</ul>
как-то так...