CodeIgniter创建n级深度导航 [英] CodeIgniter create n-level deep navigation

查看:109
本文介绍了CodeIgniter创建n级深度导航的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要一些帮助。我创建了一个动态菜单导航栏,显示菜单项根据我设置它们的顺序。我使用此 nestnedortable 插件订购我的菜单项,但目前我的菜单只有2个级别,所以基本上是这样:

  Item1 
Item2
> Subitem2.1
> Subitem2.2
Item3

do是做n级,所以基本上是这样的:

  Item1 
Item2
; Subitem2.1
>> Subitem2.1.1
> Subitem2.2
Item3
等等

级深。问题是,如果我为我的菜单项设置一个新的订单,超过2级深,我得到一个错误,订单不存储在数据库中。如何解决这个问题?



数据库结构如下:

  $ b id(pk)
menu_item
parent_id //它是父菜单项的ID
order

这是我的主要(模型)函数:

 菜单项
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)
- >其中($ this-> _primary_key,$ item ['item_id'])
- > update($ this-> _table_name);
}
}
}
}

//从最后一个订单集中获取菜单项(父母和子女)
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){

//该项目没有父项
if(!$ item ['parent_id']){
$ arr [$ item ['id']] = $ item; //例如$ arr(4 => array())
} //该项是一个子项
else {
// $ arr(4 => array('children'=> array()))
$ arr [$ item ['parent_id']] ['children'] [] = $ item;
}
}
return $ arr;
}



更新



对于其他帮助:我在两种情况下都进行了测试并转储了屏幕上的项目数组:



第一种情况: (目前为止):我用此订单设置项目




  • Item1

  • Item2

    • Item4






,结果如下所示:

  Array 

[1] => Array

[id] => 1
[menu_item] => Item1
[parent_id] => 0


[2] => Array

[id] => 2
[menu_item] => Item2
[parent_id] => 0
[children] => Array

[0] =& b(
[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



第二种情况:请按以下顺序设置菜单项:




  • Item1

  • Item2

    • Item5

      • Item4



  • Item3



,结果如下所示:

 数组

[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] =& b $ b [menu_item] => Item4
[parent_id] => 4







这是我得到错误,不工作的情况。我得到的错误是:



消息:未定义的索引:page_id
消息:未定义的索引:menu_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']。'>'; //这里是第一个错误的行
$ output。='< div>'。 $ item ['menu_item']。 '< / div>'; //第二个错误

//检查是否有子项
if(isset($ item ['children'])&&& ){
$ output。= nav($ item ['children'],true);
}
$ output。='< / li>';
}
$ output。='< / ol>';
}
return $ output;
}


echo nav($ menu_items);


解决方案

考虑到数据库输出,在数据库中正确。而且问题属于 get_menu()方法及其算法创建输出。



为了创建



这里我们来:


$

b $ b

  function prepareList(array $ items,$ pid = 0)
{
$ output = array

#通过项目
foreach($ items as $ item){

#项目的parent_id是否匹配当前的$ pid
if((int)$ item ['parent_id'] == $ pid){

#递归调用函数,使用项目的id作为父级的id
#函数返回列表或者一个空数组()
if($ children = prepareList($ items,$ item ['id'])){

#存储当前项目的所有子项
$ item ['children'] = $ children;
}

#填充输出
$ output [] = $ item;
}
}

return $ output;
}

您可以使用上述逻辑作为帮助



然后在 get_menu中调用函数/方法(在CodeIgniter中)或私有 ()方法如下:

  public function get_menu b $ b {
$ 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() everywhere(甚至在函数本身) p>

以下是 在线演示


I'd like some help please. I have created dynamic a menu navbar that displays the menu items accoridning to the order that I've set them. I'm using this nestedsortable plugin, to order my menu items, but currently my menu has only 2 levels, so basicly it goes like this:

Item1
Item2
 > Subitem2.1
 > Subitem2.2
Item3
etc etc.

What I'd like to do is make it with n-levels, so basicly something like this:

Item1
Item2
  > Subitem2.1
    >> Subitem2.1.1
  > Subitem2.2
Item3
etc etc.

and each item can go n-level deep. The problem is that if I set a new order to my menu items that is more than 2 levels deep I get an error and the order is not stored in the database. How can I fix this please ???

The database structure is this:

table: Menu
id (pk)
menu_item
parent_id // it is the id of the parent menu item
order

Here are my main (model) functions:

// 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;
 } 

Update

For additional help: I did a test and dumped the array of the items on the screen in both cases:

1st case: with 2 levels (as it is currently): I set the items with this order

  • Item1
  • Item2
    • Item4
  • Item3
  • Item5

and the result looks like this, as expected:

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
        )

)

2nd case: with n-levels: I tried to set the menu items with this order:

  • Item1
  • Item2
    • Item5
      • Item4
  • Item3

and the result looks like this:

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
                        )

                )

        )

)

This is the case where I get the error and not working. The errors I get are:

Message: Undefined index: page_id Message: Undefined index: menu_item

in my view file:

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); 

解决方案

Considering the database output, it seems the items are stored in the database correctly. And the problem belongs to the get_menu() method and its algorithm to create the output.

In order to create a n-level deep menu, you should iterate through the items recursively.

Here we go:

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;
}

You could use the above logic as a helper function (in CodeIgniter) or a private method within your Controller class.

Then call that function/method inside get_menu() method as follows:

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);
}

Note: I used the prepareList() as a helper (global) function. If you decide to use that as a private method, you should replace the function name by $this->prepareList() everywhere (even inside the function itself).

Here is the Online Demo.

这篇关于CodeIgniter创建n级深度导航的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆