php通过关联数组进行解析



我正在尝试生成一个安装在机架中的设备的动态列表。假设我有以下mysql数据:

ID    Name          Order  Owner Units
--------------------------------------
56    9U Rackmount  0      0     9.0
54    Rackmount     8      56    1.2
9    RPi 4 B       2      59    0.1
7    MacMini B     2      54    0.1
32    Router        1      56    1.0
14    RPi 4 C2      4      59    0.1
33    Switch A      2      56    1.0
35    POE Switch    3      56    1.0
8    RPi 4 A       1      59    0.1
13    RPi 4 C1      3      59    0.1
59    Rackmount     4      56    1.4
28    Powerstrip    5      56    1.0
38    Switch B      6      56    1.0

我想通过关联数组生成列表(如下((可能使用$order作为键(?"单位"列可以帮助描述设备将占用的单位数量;整数是垂直的,而十进制值是水平单位:

9U Rackmount [56]
--------------------------
1:    Router [32]
2:    Switch A [33]
3:    POE Switch [35]
4:    Rackmount [59]
1:  RPi 4 A [8]
2:  RPi 4 B [9]
3:  RPi 4 C1 [13]
4:  RPi 4 C2 [14]
5:    Powerstrip [28]
6:    Switch B [38]
7:    (empty)
8:    Rackmount [54]
1:  (empty)
2:  MacMini B [7]
9:    (empty)

这就是我提出的(递归函数(,但它甚至没有生成正确的顺序。。

function tree_build ($item) {
$found = array(); $branch = array();
$branch = get_children_via_owner($item);
$order = get_placement_within_owner($item);
if (count($branch) > 0) {
foreach ($branch as $twig) { $found[] = tree_build($twig); }
} else {
return(array($order => $item))
}
return(array(array($order => $item), $found));
}

有什么想法吗?

是的,递归函数的方向是正确的,但您没有显示get_children_via_ownerget_placement_within_ownertree_build在做什么,而且没有排序,似乎也没有考虑空元素。

递归函数应该做3件事:

  • 搜索初始数组以查找所有具有您正在评估的父数组的数组
  • 根据Order对数组进行排序
  • 将缺少的值添加为空槽

以下是代码中的样子:

function buildTree(int $Owner = 0) {
global $racks;
$ret = [];
foreach ($racks as $id => $rack) {
if ($rack['Owner'] != $Owner) { // Exclude elements with different parent
continue;
}
$rack['slots'] = buildTree($id); // Recursive
ksort($rack['slots']); // Sort based on Order
if (sizeof($rack['slots'])) {
$max_order = array_key_last($rack['slots']); 
for ($i = 1; $i <= $max_order; $i++) { // Fill empty slots
if (!isset($rack['slots'][$i])) {
$rack['slots'][] = ['Name' => '(empty)', 'ID' => 0, 'Order' => $i, 'Units' => 0];
}
}
usort($rack['slots'], function ($a, $b) {
return $b['Order'] < $a['Order'];
});
}
$ret[$rack['Order']] = $rack; // User Order as array key for easy sorting
}
return $ret;
}

然后,对于打印,您也可以编写一个递归函数,但考虑到您对每个级别使用非常不同的样式,如果您确定只有3个级别,则可能更容易执行嵌套foreach,如下所示。

foreach ($tree as $rack) {
echo $rack['Name'].' ['.$rack['ID'].']'.PHP_EOL;
echo "---------".PHP_EOL;
if (!empty($rack['slots']) && sizeof($rack['slots'])) {
foreach ($rack['slots'] as $sub1) {
echo $sub1['Order'].":    ".$sub1['Name'].' ['.$sub1['ID'].']'.PHP_EOL;
if (!empty($sub1['slots']) && sizeof($sub1['slots'])) {
foreach ($sub1['slots'] as $sub2) {
echo "        ".$sub2['Order'].":  ".$sub2['Name'].' ['.$sub2['ID'].']'.PHP_EOL;
}
}
}
}
}

除了最后一个空插槽之外,最终的输出正是您想要的,我认为您没有足够的数据来确定机架末端是否有空插槽。

9U Rackmount [56]
---------
1:    Router [32]
2:    Switch A [33]
3:    POE Switch [35]
4:    Rackmount [59]
1:  RPi 4 A [8]
2:  RPi 4 B [9]
3:  RPi 4 C1 [13]
4:  RPi 4 C2 [14]
5:    Powerstrip [28]
6:    Switch B [38]
7:    (empty) [0]
8:    Rackmount [54]
1:  (empty) [0]
2:  MacMini B [7]

作为参考,这是您生成初始阵列的方式

$tree = buildTree();

这是的初始查询

$query = 'SELECT * FROM racks ORDER BY `Owner`';
$racks = [];
if ($stmt = $sql_connection->prepare($query)) {
$stmt->execute();
$result = $stmt->get_result();
while ($data = $result->fetch_assoc()) {
$racks[$data['ID']] = $data;
}
}

最新更新