如何查找没有父页面的页面?

时间:2015-11-23 03:29:41

标签: php loops parent-child

我有一个父/子结构,可以删除父项,并且它的子项仍然会在数据库中。如果发生这种情况,最低父节点应设置为0的父节点。

我遇到了这个问题,因为我不确定如何构建我的(可能是递归的)循环。

我需要返回父母不存在的页面ID数组;例如:array(5, 9, 8);

这是我的数据集,结构可以通过父ID连接;我们可以看到页面ID 8和9具有不存在的父7:

evar_export($orphans($pages));
$data = array (
    0 => array (
        'id' => 1,
        'url' => 'Home-Page',
        'parent' => 0
    ),
    1 => array (
        'id' => 2,
        'url' => 'page1',
        'parent' => 1
    ),
    4 => array (
        'id' => 5,
        'url' => 'page4',
        'parent' => 4
    ),
    5 => array (
        'id' => 6,
        'url' => 'page5',
        'parent' => 5
    ),
    6 => array (
        'id' => 8,
        'url' => 'no-parent-1',
        'parent' => 7
    ),
    7 => array (
        'id' => 9,
        'url' => 'no-parent-2',
        'parent' => 7
    )
);

我尝试了递归,但我不知道如何抓住子树的结尾:

$orphans = function($array, $temp = array(), $index = 0, $parent = 0, $owner = 0) use(&$orphans) {
    foreach ($array as $p) {
        if($index == 0) {
            $owner = $p['id'];
        }

        if ($index == 0 || $p['id'] == $parent) {
            $temp[] = $p['id'];

            $result = $orphans($array, $temp, $index + 1, $p['parent'], $owner);

            if (isset($result)) {
                return $result;
            }
        }
        else {
            return $temp;
        }
    }
};

1 个答案:

答案 0 :(得分:2)

我将您的数据数组命名为#34;页面"对于这个例子:

$orphans = array();


foreach($pages as $p)
{   
    if($p['parent'] == 0)
        continue; //End this iteration and move on.

    $id = $p['id'];
    $parent = $p['parent'];
    $parentExists = false;
    foreach($pages as $p2)
    {
        if( $p2['id'] == $parent )
        {
            $parentExists = true;
            break; //Found, so stop looking.
        }
    }

    if(!$parentExists)
    {
        $orphans[] = $id;
    }
}

如果你在运行之后var_dump $ orphans数组,你会得到:

array(2) {
  [0]=>
  int(8)
  [1]=>
  int(9)
}

这似乎是理想的结果。不幸的是,除非你修改你的数据结构,因此需要在foreach中嵌套另一个foreach,因此ID是键(我建议减少资源使用来处理它)。使用continue / break控制结构至少可以限制使用。

对嵌套Foreach的澄清

理想的数据结构将在顺序项上使用键值对,尤其是在处理动态数据时,因为键是未知的。以您的数据为例,获取第4个项目的URL非常简单:

$id = $pages[4]['id'];

但第4项和相关数据之间没有关系/逻辑关联。它的顺序基于有史以来构建的数据。相反,如果您将id指定为键,那么我们可以轻松找到ID为4的页面的父ID:

$parent = $pages[4]['parent'];

因此,在对数据进行简单解析以查找不存在的父项时,您只需执行此操作:

foreach($pages as $p)
{   
    if($p['parent'] == 0)
        continue; //End this iteration and move on.

    $id = $p['id'];
    if(! isset($pages[$p['parent']])
    {
        $orphans[] = $id;
    }
}

因为那时我们肯定知道密钥是id,然后以这种方式逻辑处理数据。并且考虑到页面ID是主键(非重复),这应该是完全可能的。

但是如果数组中的键和值之间没有逻辑关联,我们必须查看整个数据集以查找每次迭代的匹配,从而导致资源使用的指数级爆炸以完成任务。