如何在多维数组中遵循父子关系?
How to follow parent-child relationships in a multi-dimensional array?
我有一个经典数据库 table 用于像这样的多级类别(0
表示根):
ID - Name - Father
1 News 0
2 Articles 0
3 Politics 1
4 Politics 2
5 World 3
6 World 4
我有这样的路径:/News/Articles/Politics
,并且我在数组中有上述 table 数据。
我从路径上的 /
调用 explode()
开始,我尝试了一些方法,但在所有情况下都不好。
这是我试过的东西:
$cat_path_ary = explode($cfg['categories_separator'], $cat_path);
if (count($cat_path_ary) > 1) {
$catname = array_pop($cat_path_ary);
$catparent = array_pop($cat_path_ary);
$cat_id = $this->getCatIDbyName($plugin, $catname, $catparent);
} else {
$catname = $cat_path_ary[0];
foreach($this->root_cats($plugin) as $categories) {
if($categories['name'] == $catname ) {
return $categories['cid'];
}
}
}
遍历路径值并确定最终值的最佳方法是什么ID
?
从 /News/Articles/Politics
我希望 return 5
.
我很少建议对数据库进行迭代调用,这种情况也不例外。
因为您的结果集应该相对较小,所以您可以执行完整的 table 查询并处理多维数组以获得所需的输出。
迭代路径中的条目并对符合条件的行执行迭代检查(匹配 Name
和匹配 Father
)。
由于每个内循环只能有一个符合条件的行,break
一旦找到它以获得最佳效率。 ...在这样做之前一定要更新 $id
和 $parent
变量。
已实施 "no qualifying rows" 检查,但它可能与您的项目相关,也可能不相关。您可以决定是否需要此安全网。
代码:(Demo)
$resultset = [ // query just once, collect the full tree
["ID" => 1, "Name" => "News", "Father" => 0],
["ID" => 2, "Name" => "Articles", "Father" => 0],
["ID" => 3, "Name" => "Politics", "Father" => 1],
["ID" => 4, "Name" => "Politics", "Father" => 2],
["ID" => 5, "Name" => "World", "Father" => 3],
["ID" => 6, "Name" => "World", "Father" => 4]
];
$path = "/News/Politics/World";
// $path = "/Articles/The Funnies/Garfield"; // a test case that fails
// News: parent = 0, id = 1 // \
// Politics: parent = 1, id = 3 // > the intended logic
// World: parent = 3, id = 5 // /
$cfg['categories_separator'] = "/";
$breadcrumbs = explode($cfg['categories_separator'], trim($path, "/"));
// var_export($breadcrumbs); // see what is generated
$parent = 0; // default value
foreach ($breadcrumbs as $crumb) {
$id = false; // set invalid value for success check
foreach ($resultset as $row) {
if ($row["Name"] == $crumb && $parent == $row["Father"]) { // qualifying match
$id = $parent = $row["ID"]; // dual declaration
break; // break inner loop, progress to next $crumb
}
}
if (!$id) { // inner loop failed to find qualifying match
echo "Uh-oh, Broken Breadcrumb Path -- $crumb not found in $path\n";
break; // break outer loop, path is invalid
}
// echo "ID = $id for $crumb\n"; // uncomment to see progress
}
echo "ID = $id for $crumb\n"; // echo the result
输出:
ID = 5 for World
我有一个经典数据库 table 用于像这样的多级类别(0
表示根):
ID - Name - Father
1 News 0
2 Articles 0
3 Politics 1
4 Politics 2
5 World 3
6 World 4
我有这样的路径:/News/Articles/Politics
,并且我在数组中有上述 table 数据。
我从路径上的 /
调用 explode()
开始,我尝试了一些方法,但在所有情况下都不好。
这是我试过的东西:
$cat_path_ary = explode($cfg['categories_separator'], $cat_path);
if (count($cat_path_ary) > 1) {
$catname = array_pop($cat_path_ary);
$catparent = array_pop($cat_path_ary);
$cat_id = $this->getCatIDbyName($plugin, $catname, $catparent);
} else {
$catname = $cat_path_ary[0];
foreach($this->root_cats($plugin) as $categories) {
if($categories['name'] == $catname ) {
return $categories['cid'];
}
}
}
遍历路径值并确定最终值的最佳方法是什么ID
?
从 /News/Articles/Politics
我希望 return 5
.
我很少建议对数据库进行迭代调用,这种情况也不例外。 因为您的结果集应该相对较小,所以您可以执行完整的 table 查询并处理多维数组以获得所需的输出。
迭代路径中的条目并对符合条件的行执行迭代检查(匹配 Name
和匹配 Father
)。
由于每个内循环只能有一个符合条件的行,break
一旦找到它以获得最佳效率。 ...在这样做之前一定要更新 $id
和 $parent
变量。
已实施 "no qualifying rows" 检查,但它可能与您的项目相关,也可能不相关。您可以决定是否需要此安全网。
代码:(Demo)
$resultset = [ // query just once, collect the full tree
["ID" => 1, "Name" => "News", "Father" => 0],
["ID" => 2, "Name" => "Articles", "Father" => 0],
["ID" => 3, "Name" => "Politics", "Father" => 1],
["ID" => 4, "Name" => "Politics", "Father" => 2],
["ID" => 5, "Name" => "World", "Father" => 3],
["ID" => 6, "Name" => "World", "Father" => 4]
];
$path = "/News/Politics/World";
// $path = "/Articles/The Funnies/Garfield"; // a test case that fails
// News: parent = 0, id = 1 // \
// Politics: parent = 1, id = 3 // > the intended logic
// World: parent = 3, id = 5 // /
$cfg['categories_separator'] = "/";
$breadcrumbs = explode($cfg['categories_separator'], trim($path, "/"));
// var_export($breadcrumbs); // see what is generated
$parent = 0; // default value
foreach ($breadcrumbs as $crumb) {
$id = false; // set invalid value for success check
foreach ($resultset as $row) {
if ($row["Name"] == $crumb && $parent == $row["Father"]) { // qualifying match
$id = $parent = $row["ID"]; // dual declaration
break; // break inner loop, progress to next $crumb
}
}
if (!$id) { // inner loop failed to find qualifying match
echo "Uh-oh, Broken Breadcrumb Path -- $crumb not found in $path\n";
break; // break outer loop, path is invalid
}
// echo "ID = $id for $crumb\n"; // uncomment to see progress
}
echo "ID = $id for $crumb\n"; // echo the result
输出:
ID = 5 for World