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

How to find pages without parent page?

我有一个 parent/child 结构,其中可能会删除父项,而它的子项仍将在数据库中。如果发生这种情况,最低父级应设置为 0 的父级。

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

我需要 return 一个父级不存在的页面 ID 数组;示例:array(5, 9, 8)

这是我的数据集,可以通过parent 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;
        }
    }
};

我为这个例子命名了你的数据数组 "pages":

$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:

的页面的 parent id
$parent = $pages[4]['parent'];

因此,当对数据进行简单解析以查找 non-existing 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 之类的东西是主键 (non-duplicate),这应该是完全可能的。

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