[英]Build recursive nested menu from array
我正在嘗試構建一個遞歸菜單,完成后看起來像這樣,具有無限數量的嵌套項目:
Homepage
Services
Members
Brokers
Insurers
Products
我的數據通過我表中的一個簡單的parent_id
列鏈接在一起。
我目前已設法獲取表中的所有頁面,並根據其parent_id
(見下文)將它們添加到數組中。
Array
(
[0] => 0-0-1 0-1-2 0-2-12 0-3-27 0-4-28 0-5-29 0-6-30 0-7-31 0-8-33
[2] => 2-0-3 2-0-6 2-0-7 2-0-8
[3] => 3-0-4 3-0-5
[8] => 8-0-9 8-0-10
[12] => 12-0-13 12-0-20
[13] => 13-0-14 13-1-15 13-2-17 13-3-16 13-4-19 13-5-18 13-9-34
[20] => 20-0-21 20-1-22 20-2-24 20-3-23 20-4-26 20-5-25 20-6-11
)
這被格式化為 [ parent_id
] => parent_id
- sort_order
- id
parent_id
- sort_order
- id
等等。
到目前為止,我的代碼如下:
$sqlGetDropdownPages = "SELECT * FROM `cms_staticPages` ORDER BY `sortOrder` ASC";
$qryGetDropdownPages = mysql_query($sqlGetDropdownPages) or die(mysql_error());
$resGetDropdownPages = mysql_fetch_assoc($qryGetDropdownPages);
$totGetDropdownPages = mysql_num_rows($qryGetDropdownPages);
do {
$pageArray[$resGetDropdownPages['parent_id']] .= $resGetDropdownPages['parent_id'].'-'.$resGetDropdownPages['sortOrder'].'-'.$resGetDropdownPages['id'].' ';
} while($resGetDropdownPages = mysql_fetch_assoc($qryGetDropdownPages));
ksort($pageArray);
foreach($pageArray as $i => $value) {
$explodePages = explode(' ',$value);
foreach(array_filter($explodePages) as $i2 => $page) {
$pageInfoExplode = explode('-',$page);
$getPageInfo = mysql_fetch_assoc(mysql_query("SELECT * FROM `cms_staticPages` WHERE `id` = '".$pageInfoExplode[2]."'"));
echo $getPageInfo['identifier'].'<br />';
}
}
此時撞到了一堵磚牆,不知道下一步該怎么做。
我試圖盡可能地解釋這一點,所以如果需要任何澄清,請詢問。
如何實現這一目標?
我會首先按 id 索引所有菜單項(頁面)。 在第二個循環中,將菜單項與其父項相關聯並跟蹤頂級項。
我會這樣做的方法之一(Render方法只是一個例子):
$sqlGetDropdownPages = "SELECT * FROM `cms_staticPages` ORDER BY `sortOrder` ASC";
$qryGetDropdownPages = mysql_query($sqlGetDropdownPages) or die(mysql_error());
//indexing pages by id
while ($pageRow = mysql_fetch_assoc($qryGetDropdownPages)) {
$menuItems[$pageRow['id']] = new MenuItem($pageRow);
}
//associating pages with parents
foreach ($menuItems as $menuItem) {
if ($menuItem->hasParent()) {
$menuItem->addToParent($menuItems);
} else {
$topLevel[] = $menuItem;
}
}
//$topLevel is an array of menuItems without parents
$render = '<ul>';
foreach ($topLevel as $menuItem) {
$render .= $menuItem->render(true);
}
$render .= '</ul>';
MenuItem 類看起來像這樣
class MenuItem {
/**
* @var array
*/
private $data;
/**
* @var MenuItem[]
*/
private $children = array();
/**
* @var MenuItem
*/
private $parent;
/**
* @param array $data
*/
public function __construct($data) {
$this->data = $data;
}
/**
* Finds the parent in the collection and adds itself to it
* @param MenuItem[] $menuItems
*/
public function addToParent($menuItems) {
if (isset($menuItems[$this->data['parent_id']])) {
$this->parent = $menuItems[$this->data['parent_id']];
$this->parent->addChild($this);
}
}
/**
* @return bool
*/
public function hasParent() {
return empty($this->data['parent_id']);
}
/**
* @param MenuItem $child
*/
public function addChild(MenuItem $child) {
$this->children[] = $child;
}
/**
* Renders the menu with ul li
* @param bool $withChildren
* @return string
*/
public function render($withChildren = false) {
$render = '<li>' . $this->data['identifier'] . '</li>';
if ($withChildren) {
$render .= '<ul>';
foreach ($this->children as $child) {
$render .= $child->render(true);
}
$render .= '</ul>';
}
return $render;
}
}
這是我使用 PHP 中的遞歸函數為 Zurb Foundation 構建嵌套菜單的示例代碼。 非常簡單和干凈。
// call the function
build_menu();
//----------------------------
// recursive function
function build_menu($parent = "", $tab=""){
$sql = "SELECT * FROM cat WHERE parent='$parent' ORDER BY category ASC";
$q = mysql_query($sql);
if (mysql_num_rows($q)) {
if (empty($parent)):
print $tab."<ul>\n";
else:
print $tab."<ul class='dropdown'>\n";
endif;
while($d = mysql_fetch_object($q)) {
$has_child = mysql_num_rows(mysql_query("select * from cat where parent='$d->code'") );
$tag = ($has_child ? " class='has-dropdown'" : "");
$nl = ($has_child ? "\n" : "");
print $tab."\t"."<li".$tag."><a href='cat.php?cat=$d->code'>$d->category</a>$nl";
if ($has_child) build_menu($d->code, $tab."\t");
print $tab."</li>\n";
}
print $tab."</ul>\n";
}
}
假設從數據庫中提取所有菜單項后,輸出如下輸出。
$items = [
[
'id' => '1',
'parent_id' => '0',
'title' => 'Menu 1',
],
[
'id' => '2',
'parent_id' => '0',
'title' => 'Menu 2',
],
[
'id' => '3',
'parent_id' => '2',
'title' => 'Menu 2 1',
],
[
'id' => '4',
'parent_id' => '0',
'title' => 'Menu 3',
],
[
'id' => '5',
'parent_id' => '4',
'title' => 'Menu 3 1',
],
[
'id' => '6',
'parent_id' => '5',
'title' => 'Menu 3 1 1',
],
[
'id' => '7',
'parent_id' => '5',
'title' => 'Menu 3 1 2',
],
[
'id' => '8',
'parent_id' => '7',
'title' => 'Menu 3 1 2 1',
],
[
'id' => '9',
'parent_id' => '4',
'title' => 'Menu 3 2',
],
[
'id' => '10',
'parent_id' => '0',
'title' => 'Menu 4',
]];
讓我們寫一個函數來處理Array格式的數據並返回html
/**
* Recursive and prints the elements of the given parent id.
* @param $items
* @param string $parentId
*/
function buildNestedItems($items, $parentId = "0", $wrapperTag = 'ul', $itemTag = 'li')
{
// Parent items control
$isParentItem = false;
foreach ($items as $item) {
if ($item['parent_id'] === $parentId) {
$isParentItem = true;
break;
}
}
// Prepare items
$html = "";
if ($isParentItem) {
$html .= "<$wrapperTag>";
foreach ($items as $item) {
if ($item['parent_id'] === $parentId) {
$html .= "<$itemTag>" . $item['title'] . "</$itemTag>";
$html .= buildNestedItems($items, $item['id']);
}
}
$html .= "</$wrapperTag>";
}
return $html;
}
讓我們打印准備好的 html i 頁面
<div class="menu">
<?php echo buildNestedItems($items); ?>
</div>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.