0

我不确定这是否完全符合我的措辞,但我们开始吧:我试图弄清楚如何在 php 中创建一个递归循环,该循环基本上检查子列是否为空 - 如果该子元素列有一个空值,然后它使用父ID递归地遍历其祖先,直到找到具有该列的值的父,然后将该父值放入原始子列中。由于我刚开始使用 php,但我对数据库和 mysql 有深入的了解,因此我对此感到非常困惑。任何帮助和代码示例都会很棒。

4

2 回答 2

0

关于使用邻接列表模型存储分层数据的警告:它以易于创建和更新表为代价换取了重新获取数据的效率低下。我个人在我的项目中使用了Closure Tables,因为即使弄清楚如何在其中获取数据以及如何更新它们是很疯狂的,但在重新获取数据方面效率要高得多。如果您有 Closure Tables,您可以使用一个查询来获取节点的所有具有信息的父节点的列表,并使用 ORDER BY Distance LIMIT 1 来获取您想要的父节点作为您的答案。使用嵌套集也可以是一种选择,尽管我对它们知之甚少。在继续之前,您应该研究这些并考虑您的选择。

这是您现在拥有的邻接列表:

$target = 4; //whatever ID
$db = new mysqli(HOST, USERNAME, PASSWORD, DATABASE);

if($db->connect_errno > 0){
    die('Unable to connect to database [' . $db->connect_error . ']');
}
$statement = $db->prepare("SELECT ParentID, Audience FROM things WHERE ChildID = ?");

$audience = NULL;
$ChildID = $target; // starts as same value
while(!isset($audience) || !isset($ChildID)) {  //This assumes that the top ParentID is null; you might have to adjust it
     $statement->bind_param('i', $ChildID);
     $statement->execute();
     $result = $statement->get_result();
     while($row = $result->fetch_assoc()){
         if(!isset($row['Audience']) && !isset($audience)) {
             $ChildID = isset($row['ParentID'])?$row['ParentID']:NULL;
         } else {
             $audience = $row['Audience'];
         }
     }
     $result->free();
}

if(isset($audience)) {
    if($target == $ChildID) { //it was found on that first try
         echo $audience.' was found for '.$target;
    } else {
        $statement = $db->prepare("UPDATE things SET Audience = ? WHERE ChildID = ?");
        $statement->bind_param('si', $audience, $target); 
        $statement->execute();
        echo $audience.' was set for '.$target;
    }
} else {
    echo 'No audience was found or set for '.$target;
}


$db->close();

请注意,bind_param 的第一个参数关心您的绑定对象是什么类型(字符串、整数、小数、blob)。你可能需要查一下。

于 2013-10-15T21:10:22.707 回答
0

请提供示例表/字段。我们不知道您是指一张桌子还是几张桌子。

您的 php 代码可能看起来像这样(查询内容是伪代码)

function updateChild($ChildID,$ParentID=-1)
{
    //use mysqlquery or whatever
    if($ParentID==-1)
       select field_value,parent_id from mytable where rowid=$ChildID; 
    else
       select field_value,parent_id from mytable where parentid=$ParentID;
    $candidate_value=$row['field_value'];
    $fallback_parent=$row['parent_id']

    if (  is_null($candidate_value))
        updateChild($ChildID, $fallback_parent)
    else
        update mytable set field_value=$candidate_value where $ChildID=$ChildID   
}

想法是您首先获取当前字段值和 parentID 以防万一。如果结果为空,则再次调用相同的函数,传入子项或 rowid 以及下一个要检查的父项。如果父母证明是好的,它会使用一直传递的子值进行更新。请注意,如果在第一次尝试时确实有值,上面的代码将使用“自身”更新子值,因此应该通过检查 parentid 是否为 -1 来解决这个问题。

于 2013-10-15T20:53:09.727 回答