我想提供一些帮助。我创建了一个动态菜单纳维尔(Navbar),该菜单显示了我设置的菜单项。我正在使用此NestedSortable插件来订购我的菜单项,但是目前我的菜单只有2个级别,因此基本上是这样的:
Item1
Item2
> Subitem2.1
> Subitem2.2
Item3
etc etc.
我想做的就是与n级别一起做,因此基本上是这样的:
Item1
Item2
> Subitem2.1
>> Subitem2.1.1
> Subitem2.2
Item3
etc etc.
每个项目都可以深入n级。问题是,如果我为深度超过2个级别的菜单项设置新订单,我会遇到错误,并且该订单不会存储在数据库中。我该如何解决???
数据库结构是这样的:
table: Menu
id (pk)
menu_item
parent_id // it is the id of the parent menu item
order
这是我的主要(模型)函数:
// save the order of the menu items
public function save_order($items){
if (count($items)>0) {
foreach ($items as $order => $item) {
if ($item['item_id'] != '') {
$data = array(
'parent_id' => (int)$item['parent_id'],
'order' => $order
);
$this->db->set($data)
->where($this->_primary_key, $item['item_id'])
->update($this->_table_name);
}
}
}
}
// fetch the menu items (parents & children) from the last order set
public function get_menu(){
$this->db->select('id, menu_item, parent_id');
$this->db->order_by('parent_id, order');
$menu_items = $this->db->get('menu')->result_array();
$arr = array();
foreach ($menu_items as $item) {
// the item has no parent
if (!$item['parent_id']) {
$arr[$item['id']] = $item; // e.g. $arr(4 => array())
} // the item is a child
else {
// e.g. $arr(4 => array('children' => array()))
$arr[$item['parent_id']]['children'][] = $item;
}
}
return $arr;
}
更新
以获取其他帮助:在两种情况下,我都进行了测试,并将项目的数组丢在屏幕上:
第1个情况:具有2个级别(当前与当前一样):我用此顺序设置项目
- item1
- 项目2
- item4
- item3
- item5
,结果看起来像这样,如预期:
Array
(
[1] => Array
(
[id] => 1
[menu_item] => Item1
[parent_id] => 0
)
[2] => Array
(
[id] => 2
[menu_item] => Item2
[parent_id] => 0
[children] => Array
(
[0] => Array
(
[id] => 4
[menu_item] => Item4
[parent_id] => 2
)
)
)
[3] => Array
(
[id] => 3
[menu_item] => Item3
[parent_id] => 0
)
[5] => Array
(
[id] => 5
[menu_item] => Item5
[parent_id] => 0
)
)
第二个情况:带有n级别:我尝试使用此顺序设置菜单项:
- item1
- 项目2
- 项目5
- item4
- 项目5
- item3
结果看起来像这样:
Array
(
[1] => Array
(
[id] => 1
[menu_item] => Item1
[parent_id] => 0
)
[2] => Array
(
[id] => 2
[menu_item] => Item2
[parent_id] => 0
[children] => Array
(
[0] => Array
(
[id] => 5
[menu_item] => Item5
[parent_id] => 2
)
)
)
[3] => Array
(
[id] => 3
[menu_item] => Item3
[parent_id] => 0
)
[4] => Array
(
[children] => Array
(
[0] => Array
(
[id] => 4
[menu_item] => Item4
[parent_id] => 4
)
)
)
)
我会遇到错误而无法正常工作的情况。我遇到的错误是:
消息:未定义的索引:Page_id消息:未定义的索引:菜单_item
在我的视图文件中:
function nav($menu_items, $child = false){
$output = '';
if (count($array)) {
$output .= ($child === false) ? '<ol class="sortable">' : '<ol>' ;
foreach ($menu_items as $item) {
$output .= '<li id="list_' . $item['id'] . '">'; // here is the line of the 1st error
$output .= '<div>' . $item['menu_item'] . '</div>'; // 2nd error
//check if there are any children
if (isset($item['children']) && count($item['children'])) {
$output .= nav($item['children'], true);
}
$output .= '</li>';
}
$output .= '</ol>';
}
return $output;
}
echo nav($menu_items);
考虑数据库输出,似乎这些项目已正确存储在数据库中。问题属于get_menu()
方法及其算法来创建输出。
为了创建 n级深度菜单,您应该递归通过项目迭代。
我们去:
function prepareList(array $items, $pid = 0)
{
$output = array();
# loop through the items
foreach ($items as $item) {
# Whether the parent_id of the item matches the current $pid
if ((int) $item['parent_id'] == $pid) {
# Call the function recursively, use the item's id as the parent's id
# The function returns the list of children or an empty array()
if ($children = prepareList($items, $item['id'])) {
# Store all children of the current item
$item['children'] = $children;
}
# Fill the output
$output[] = $item;
}
}
return $output;
}
您可以将上述逻辑用作助手函数(在CodeIgniter中)或 private 您的控制器类中的方法。
然后在get_menu()
方法中调用该函数/方法如下:
public function get_menu()
{
$this->db->select('id, menu_item, parent_id');
$this->db->order_by('parent_id, order');
$menu_items = $this->db->get('menu')->result_array();
return prepareList($menu_items);
}
注意:我将prepareList()
用作助手(全局)功能。如果您决定将其用作私有方法,则应通过$this->prepareList()
替换函数名称(甚至在功能本身内)。
这是在线演示。