2012-08-16 60 views
2

我试图创建一个“插件”之类的脚本添加到“菜单阵” ......我会去直接在导航/ subnav结构..PHP - 从阵列

可以说我发起导航项目如下:

$sections->add_section('dashboard'); 
$DashBoardSection = $sections->load_section('dashboard'); 
$DashBoardSection->set_role(NULL); 
$DashBoardSection->set_nav_item(array(
    'identifier' => 'dashboard', 
    'text' => 'Dashboard', 
    'url' => NULL, 
    'position' => NULL 
)); 

首先创建一个新的部分并获取实例。

然后,我们设置一个“角色”,我们将在其中测试以查看用户是否已通过身份验证以查看。

设置导航项只存储数组。标识符是对项目的引用(当我们想要添加子项目时),除了“位置”之外的所有标准,它说明它位于nav中的位置,即NULL是顶层,数组('topnav','subnav ')将是topnav-> subnav->仪表板。

的测试,这可以存储如下:

Array 
(
    [0] => Array 
     (
      [identifier] => dashboard 
      [text] => Dashboard 
      [url] => 
      [position] => 
     ) 
[1] => Array 
    (
     [identifier] => dashboard2 
     [text] => Dashboard2 
     [url] => 
     [position] => Array 
      (
       [0] => dashboard 
      ) 

    ) 

) 

我的问题是我怎么把它转换成以下结构:

Array 
(
    [0] => Array 
    (
     [identifier] => dashboard 
     [text] => Dashboard 
     [url] => 
     [position] => 
     [children] => Array 
      (
       [0] => Array 
        (
         [identifier] => dashboard2 
         [text] => Dashboard2 
         [url] => 
        ) 
      ) 
    ) 
) 

拉我的头发在这一项,任帮助将非常感激。

问候

我现在有

public function build_navigation($role){ 
    $role = (int)$role; 
    $nav = array(); 
    foreach($this->sections as $section) { 
     if($section->get_role() === NULL || $section->get_role() === $role) { 
      $nav_array = $section->get_nav(); 
      foreach($nav_array as $key => $nav_item) { 
       if($nav_item['position'] === NULL) { 
        $nav[$nav_item['identifier']] = $nav_item; 
       }elseif(is_array($nav_item['position'])){ 
        #...# 
       } 
      } 
     } 
    } 
    return $nav; 
} 

编辑

想象这是给定的数组(它可以在任何顺序)

Array 
(
    [0] => Array 
     (
      [identifier] => dashboard_child2 
      [text] => Dashboard Child 2 
      [url] => 
      [position] => Array 
       (
        [0] => dashboard 
       ) 

     ) 

    [1] => Array 
     (
      [identifier] => dashboard_child_child_1 
      [text] => Dashboard Child Child 1 
      [url] => 
      [position] => Array 
       (
        [0] => dashboard 
        [1] => dashboard_child1 
       ) 

     ) 



[2] => Array 
    (
     [identifier] => dashboard_child1 
     [text] => Dashboard Child 1 
     [url] => 
     [position] => Array 
      (
       [0] => dashboard 
      ) 

    ) 

[3] => Array 
    (
     [identifier] => dashboard 
     [text] => Dashboard 
     [url] => 
     [position] => 
    ) 

[4] => Array 
    (
     [identifier] => dashboard2 
     [text] => Dashboard2 
     [url] => 
     [position] => Array 
      (
       [0] => dashboard 
      ) 

    ) 

) 

一个需要格式为:

Array 
(
    [dashboard] => Array 
     (
      [text] => Dashboard 
      [url] => 
      [children] => Array 
       (
        [dashboard_child2] => Array 
         (
          [text] => Dashboard Child 2 
          [url] => 
         ) 
        [dashboard_child1] => Array 
         (
          [text] => Dashboard Child 1 
          [url] => 
          [children] => Array 
           (
            [dashboard_child_child_1] => Array 
             (
              [text] => Dashboard Child Child 1 
              [url] => 
             ) 
           ) 
         ) 
        [dashboard2] => Array 
         (
          [text] => Dashboard2 
          [url] => 
         ) 
       ) 
     ) 
) 
+0

[嵌套数组可能重复。第三级消失](http://stackoverflow.com/questions/7673044/nested-array-third-level-is-disappearing) – hakre 2012-08-16 20:55:03

回答

2

这是我对问题的看法,用递归解决。

你可以使用多个职位(我猜这就是为什么它是一个数组),如果至少有一个职位被发现,它会忽略缺少的职位,但是如果每个职位都没有,就会抱怨。

function translate($in) { 

    $out = array(); 

    // first pass, move root nodes to output 
    foreach ($in as $k => $row) { 
     if (!$row['position']) { 
      $out[$row['identifier']] = $row; 
      unset($in[$k]); 
     } 
    } 

    // while we have input 
    do { 
     $elements_placed = 0; 
     // step trough input 
     foreach ($in as $row_index => $row) { 
      foreach ($row['position'] as $pos) { 
       // build context for the node placing 
       $data = array(
        'row' => $row, 
        'in' => &$in, 
        'row_index' => $row_index, 
        'elements_placed' => &$elements_placed, 
        'pos' => $pos, 
       ); 
       // kick of recursion 
       walker($out, $data); 
      } 
     } 
    } while ($elements_placed != 0); 
    if (count($in)) { 
     trigger_error("Error in user data, can't place every item"); 
    } 
    return $out; 
} 

function walker(&$out, $data) { 
    foreach ($out as &$row) { 
     // it looks like a node array 
     if (is_array($row) && isset($row['identifier'])) { 
      // if it has children recurse in there too 
      if (isset($row['children'])) { 
       walker($row['children'], $data); 
      } 

      // it looks like a node array that we are looking for place the row 
      if ($row['identifier'] == $data['pos']) { 
       if (!isset($row['children'])) { 
        $row['children'] = array($data['row']['identifier'] => $data['row']); 
       } else { 
        $row['children'][$data['row']['identifier']] = $data['row']; 
       } 
       // report back to the solver that we found a place 
       ++$data['elements_placed']; 
       // remove the row from the $in array 
       unset($data['in'][$data['row_index']]); 
      } 
     } 
    } 
} 

$in = array (
    array (
     'identifier' => 'secondlevelchild2', 
     'text' => 'secondlevelchild2', 
     'url' => '', 
     'position' => array (
      'dashboard2', 
     ), 
    ), 
    array (
     'identifier' => 'secondlevelchild', 
     'text' => 'secondlevelchild', 
     'url' => '', 
     'position' => array (
      'dashboard2', 
     ), 
    ), 
    array (
     'identifier' => 'dashboard', 
     'text' => 'Dashboard', 
     'url' => '', 
     'position' => '', 
    ), 
    array (
     'identifier' => 'dashboard2', 
     'text' => 'Dashboard2', 
     'url' => '', 
     'position' => array (
      'dashboard', 'home', 
     ), 
    ), 
    array (
     'identifier' => 'thirdlevelchild', 
     'text' => 'thirdlevelchild', 
     'url' => '', 
     'position' => array (
      'secondlevelchild2', 
     ), 
    ), 
); 

$out = translate($in); 
var_export($out); 

在它的当前形式不一旦被放置在距离阵列节点移除identifierposition密钥。

+0

似乎无法得到这个正常工作,不断把所有东西作为仪表板的直接子... http://pastebin.com/uWuX0QeU – 2012-08-16 20:26:16

+0

哦,我错误地解释了'position'数组的含义(基于在原始问题上)。有了这个版本,你不必一路列出每一个父母,只有最近的一个(在我的例子中,'thirdlevelchild'只有'secondlevelchild2'的位置,get的放置正确)。但是有了完整的路径,它也可以更容易地完成( - : – complex857 2012-08-16 20:30:53

+0

啊,我看到是的。原来的“位置”映射数组值的路径,但你的方式增加了多个...认为这可能更好! AHA!天才,谢谢你们两位! – 2012-08-16 20:32:44

2

您需要一个临时数组,将标识符映射到它的子数组,以便您可以将它添加到那里。

如果我看到正确的,你有类似的东西已经在这里当你添加父:

$nav[$nav_item['identifier']] = $nav_item; 

编辑:添加父需要如指出了一些注意事项评论:

$node = &$nav[$nav_item['identifier']]; 
$children = isset($node['children']) ? $node['children'] : array(); 
$node = $nav_item; 
$node['children'] = $children; 
unset($node); 

只需加给孩子,然后:

foreach($nav_item['position'] as $identifier) 
{ 
    $nav[$identifier]['children'][] = $nav_item; 
} 

你也可以使用对象,而不是数组,这样你就不会重复数据那么多(或者你可以在以后改变它),但是,只是在想,这解决您的问题一定不是必要的,所以稍后可能会有所帮助。

+0

这就是我的问题......如果它被设置为插件范围/环境,没有理由为什么在标识符'foo'或'bar'之前读取位置为'array('foo','bar','foobar')'的部分...所以密钥不会设置在临时数组中...... – 2012-08-16 19:09:40

+0

I知道你已经花了上面的时间,但我不知道这将如何工作......让我创建一个数据,我在我的脑海中看到,这将导致问题的数组... – 2012-08-16 19:16:56

+0

我已经添加了一个数据结构这个问题... – 2012-08-16 19:30:51