访问我编写的脚本时,访问页面时将类别路径传递给它。然后,脚本会将数据与应与该类别相关联的实际类别数组或分支进行比较。
我将父母及其所有子代设置为tree
,然后在分支下进行比较并比较数据,以确保客户使用正确的url。这是代码工作原理的快速示例:
// Customer is accessing from site.com/store/some-cat/some-othercat
// We pass those variables with the htaccess to script.php?var=$1,$2
// We then explode that to make an array on $var[0] and $var[1]
$categoryMap = explode(",", $_GET['var']);
$categoryID = array();
$categoryInfoMap = array();
foreach ($categoryMap as $a) {
$categoryIDs[] = trim($a);
}
$getCategoryInfo = $db->fn->query("SELECT * FROM store_category");
....
// Inside while loop...
$categoryInfoMap[] = $db->result[]; // stored whole results as array
// End of the while loop
$masterKey = $mainClass->findKeyInDbArray($categoryInfoMap, 'c.path', $categoryMap[0]);
if ((isset($masterKey) && $masterKey === "0") || !empty($masterKey)) {
$thisId = $categoryInfoMap[$masterKey]['c.id'];
$thisPath = $categoryInfoMap[$masterKey]['c.path'];
$thisName = $categoryInfoMap[$masterKey]['c.name'];
$tree = $mainClass->buildTree($categoryInfoMap);
$children = $tree['children'][$thisId];
$childrenItems = "";
foreach ($categoryIDs as $cid) {
// One of the categories entered doesnt exist at all so we redirect,
// else we will go through them and make sure theyre apart of the branch
if (!$mainClass->recursive_array_search($cid, $tree)) {
... redirect them somewhere and die()
} else {
if (!$mainClass->recursive_array_search($cid, $children)) {
... redirect them somewhere and die()
} else {
!!!!!!!!!!!!============!!!!!!!!!!!!!!
THIS IS THE IMPORTANT PART HERE
!!!!!!!!!!!!============!!!!!!!!!!!!!!
}
}
}
}
... Rest of the script which works for now
以下是上面代码中使用的功能
public function findKeyInDbArray($products, $field, $value) {
foreach($products as $key => $product) {
if ($product[$field] === $value) {
return "$key";
}
}
return NULL;
}
public function buildTree($arr) {
$tree = array(
'children' => array()
);
$index = array(0=>&$tree);
foreach ($arr as $key => $val) {
$parent = &$index[$val['c.parentcatid']];
$node = $val;
$parent['children'][$val['c.id']] = $node;
$index[$val['c.id']] = &$parent['children'][$val['c.id']];
}
return $tree;
}
public function recursive_array_search($needle,$haystack) {
foreach($haystack as $key=>$value) {
$current_key=$key;
if($needle===$value OR (is_array($value) && $this->recursive_array_search($needle,$value) !== false)) {
return $current_key;
}
}
return false;
}
这是从父节点开始向下的树数组的示例。由于可见性原因而被短路
Array(
[c.id] => 1
[c.name] => Radios
[c.path] => radios
[c.parentcatid] => 0
[children] => (
[2] => (
[0] => 2
....
[children] => (
[3] => (
[c.id] => 3
....
[c.parentcatid] => 2
),
[4] => (
[c.id] => 4
....
[c.parentcatid] => 2
)
)
)
......
[10] => (
[0] => 10
....
[c.parentcatid] => 1
)
)
SO进入好位置
现在,代码正在努力证明分支具有来自其树的匹配变量。如果项目路径(这是我们用来与url $var
比较的变量)匹配,则它将继续运行。因此,如果分支中存在以下值:
array(c.path => 'foo'),
array(c.path => 'bar')
我以site.com/store/foo/bar
的身份访问脚本,然后一切正常。如果我以site.com/store/foo/notBar
的身份访问该站点,则该站点将失败,因为notBar变量不是此分支的成员。那是完美的吧?一切都会正常!除非不是,并且有充分的理由。
此处的问题
如果该项目在分支中匹配,则它已通过检查,这是检查的结束。如果项目以错误的顺序传递,例如site.com/store/bar/foo
,则不是这样,但从技术上讲,它仍然具有良好的变量,但是由于结构的排列顺序不符合其从父数组的顺序,因此不应传递。同样,如果树上还有另一个分支,可以说barwithNoChildren
存在,即使没有应该,我也可以用它交换foo
或bar
并仍然通过>在那里。
希望您能理解我的要求,并可以帮助您提出解决方法。最近几天,我一直在这个系统上动脑筋,由于他们出于seo和其他原因想要精美的网址,所以比我计划的要困难得多。感谢您的任何建议!
答案 0 :(得分:1)
树结构实际上并没有帮助。您应该考虑如何创建一个数据结构,以使您轻松匹配输入。由于您的类别输入描述了树的分支,因此最好的方法是构建一个数组,您可以使用该数组将这些分支描述与类别有效地匹配。
让我们构建一个数组,其中的键是每个类别的路径(如它们的子句所描述),而值是类别ID。然后,我们可以立即识别出匹配的类别,如果路径不在数组中,则失败。
这种类似于面包屑的结构是类别常用的另一种模式。除了树和平面ID映射外,您几乎可以执行所需的任何操作。关键要点是考虑使用数据创建不同的结构来完成不同的任务。与创建复杂的逻辑来尝试和使用现有的,不适合手头工作的结构相比,创建一种易于使用的新结构通常更高效,更不易出错。
<?php
//Mock category records, would come from the DB in the real world
$categoryRecords = [
['id' => 1, 'title' => 'Radios', 'slug' => 'radios', 'parent_id' => 0],
['id' => 2, 'title' => 'Accessories', 'slug' => 'misc', 'parent_id' => 1],
['id' => 3, 'title' => 'Motorola', 'slug' => 'motorola', 'parent_id' => 1],
['id' => 4, 'title' => 'Handheld', 'slug' => 'handheld', 'parent_id' => 3],
['id' => 5, 'title' => 'Mobile', 'slug' => 'mobile', 'parent_id' => 3]
];
//Create an array that maps parent IDs to primary keys
$idMap = [];
foreach ($categoryRecords as $currRecord)
{
$idMap[$currRecord['id']] = $currRecord;
}
//Traverse the flat array and build the path lines
$paths = [];
$categoryIds = array_keys($idMap);
foreach ($categoryIds as $currLeafId)
{
$currCategoryId = $currLeafId;
$currLine = [];
do
{
$currLine[] = $idMap[$currCategoryId]['slug'];
$currCategoryId = $idMap[$currCategoryId]['parent_id'];
} while ($currCategoryId != 0);
$currLine = array_reverse($currLine);
$currPath = implode('/', $currLine);
$paths[$currPath] = $currLeafId;
}
//Join your input - $_GET['var'] in your example
$inputPath = implode('/', ['radios', 'motorola', 'handheld']);
//Now you can see if the incoming path matched a category
if(array_key_exists($inputPath, $paths))
{
$category = $categoryRecords[$paths[$inputPath]];
echo 'Matched category: '.$category['title'].PHP_EOL;
}
else
{
echo 'Invalid category path';
}