PHP - 通过引用将子节点添加到多级关联数组

时间:2016-06-10 15:50:46

标签: php arrays associative-array multi-level

我从MySQL获得了一个记录集,它返回给定对象的类别ID及其值。例如:

+-----------+-------------+----------------+
| object_id | category_id | category_value |
+-----------+-------------+----------------+
|         1 |           2 | VEGETARIAN     |
|         1 |           3 | MATARÓ         |
|         1 |           5 | MARCO POLO     |
|         1 |           5 | JOHN DOE       |
|         2 |           2 | VEGETARIAN     |
|         2 |           3 | MATARÓ         |
|         2 |           5 | JOHN DOE       |
+-----------+-------------+----------------+

有了这个,我需要的是PHP中的以下结果关联数组:

// They are arrays, so more than one object_id can be in the same category tree (and the object_id can be repeated across categories)

$final_array['VEGETARIAN']['MATARÓ']['MARCO POLO'] = array(1);
$final_array['VEGETARIAN']['MATARÓ']['JOHN DOE'] = array(1, 2);

查询首先按object_id排序结果,然后按category_id按用户设置顺序排序。所以,它就像ORDER BY object_id ASC, FIELD(category_id, usercat1, usercat2, usercat3)(在这种情况下是FIELD(category_id, 2, 3, 5)

我已经得到了每个集合的循环,并且我试图保留一个临时变量来存储数组级别,因为它们可以更改(并不总是3级),所以类似于:

$temporary_array['VEGETARIAN'] = array();
$temporary_array = $temporary_array['VEGETARIAN'];

// And then, on the next iteration
$temporary_array['MATARÓ'] = array();
$temporary_array = $temporary_array['MATARÓ'];
// Now, $temporary_array would be equal to $temporary_array['VEGETARIAN']['MATARÓ'];

所以我可以根据 new 类别值创建一个主键,该值将存储为父数组的子类,并获取所有分层树。 每个级别都应包含所有下一个级别

我试图在全球范围内声明它并通过引用传递它,但似乎无法正常工作。

有没有办法在PHP中实现这一点?你会如何才能获得理想的结果呢?

修改

我已经越来越接近让它颠倒了类别的顺序,所以我先得到最后一个类别(其中没有其他类别的类别)然后我向上移动数组,如下所示:

// Long story very short, would be like
$final_array['new_category_value'] = $old_final_array; 

继续为每个对象做准备。当我更改object_id时,我会:

array_merge_recursive($final_array, $actual_object_array);

但是,我仍然无法获得理想的结果。

感谢您的时间和意见!

1 个答案:

答案 0 :(得分:1)

假设您可以将SQL数据作为关联数组访问,并且'1'值是object_id(而不是true / false 0/1等),如下所示:

$sth = $dbh->prepare("SELECT ......"); //Your SQL Here
$sth->execute();
$rows = $sth->fetchAll(PDO::FETCH_ASSOC);

$ rows应该包含这样的内容:

$rows = array(
    array(
        "object_id" => 1,
        "category_id" => 2,
        "category_value" => "VEGETARIAN"
    ),
    array(
        "object_id" => 1,
        "category_id" => 3,
        "category_value" => "MATARÓ"
    ),
    array(
        "object_id" => 1,
        "category_id" => 5,
        "category_value" => "MARCO POLO"
    ),
    array(
        "object_id" => 1,
        "category_id" => 5,
        "category_value" => "JOHN DOE"
    )
); 

从这一点开始,您可以遍历行。单个行发生的情况取决于它之前的行,因此存储并更新包含该行的变量,以便可以在此循环中访问它

//Define your final array
$final_array = array();

//Store a reference to the last row in order to get the last category checked
$lastRow=null;

//Store reference to the last potential parent 
$lastParent=&$final_array;

//Store a reference to the last entry - either an array or the object id
$lastEntry = null;


//Loop over all returned rows
foreach($rows as $row) {

    //If first time around loop, $lastRow will be null
    //If $lastRow is not null, but matches this row's category_id, we should add to the same parent 
    if($lastRow===null || $lastRow['category_id']===$row['category_id']){

        $lastParent[$row['category_value']] = $row['object_id'];

        $lastEntry = &$lastParent[$row['category_value']];

        //Note - Do not change last parent here
    }

    //lastCategoryId does not match this row's category ID and is not null, we must change the 
    //  last entry to be an array and add this entry to it.
    else {
        $lastParent = &$lastEntry;

        $lastParent = array($row['category_value'] => $row['object_id']);

        $lastEntry = &$lastParent[$row['category_value']];
    }


    //Loop complete, update the last row
    $lastRow=$row;
}

您现在可以查看返回的电话print_r($final_array);

Array
(
    [VEGETARIAN] => Array
        (
            [MATARÓ] => Array
                (
                    [MARCO POLO] => 1
                    [JOHN DOE] => 1
                )

        )

)