Recursive array search - keep proper order and iterate down array
当访问我正在编写的脚本时,在访问页面时将类别路径传递给它。然后,脚本将数据与实际类别数组或应与该类别关联的分支进行比较。
我把父母和他们所有的孩子设置成一个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | // 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 |
下面是上面代码中使用的函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | 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; } |
下面是一个树数组的例子,从父节点向下。因能见度原因而短路
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | 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 ) ) |
好的部分
现在,代码正在努力证明分支具有与其树匹配的变量。如果我们用来与url
我以
这里的问题
如果项目在分支中匹配,那么它已经通过检查,并且是检查的结束。如果以错误的顺序传递项(如
希望你们能理解我的要求,并能帮我提出解决办法。最近几天,我一直在这个系统上绞尽脑汁,因为他们想通过搜索引擎优化(seo)和其他原因获得更漂亮的URL,所以这比我计划的要困难得多。谢谢你的建议!
树的结构对于这个目的并没有真正的帮助。您应该考虑如何创建一个数据结构,使您很容易匹配输入。因为您的类别输入描述了树的一个分支,所以最好是构建一个数组,您可以使用该数组来有效地将这些分支描述与类别匹配。
让我们构建一个数组,其中键是每个类别的路径,如它们的slug所描述的那样,值是类别ID。然后,我们可以立即标识匹配的类别,或者如果路径不在数组中,则会失败。
这种类似面包屑的结构是另一种常见于类别的模式。除了树和平面ID图,您可以做几乎任何您需要的事情。关键是考虑用数据创建不同的结构来完成不同的任务。通常,创建一个易于使用的新结构比创建复杂的逻辑来尝试和使用一个不适合当前任务的现有结构更有效、更不容易出错。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | <?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'; } |