[英]Recursively creating a multi-dimensional array in PHP
我試圖找出編寫 PHP 函數的最佳方法,該函數將遞歸地構建一個多維數組,該數組具有來自 mysql 表的未知數量的子級別。 它的目的是創建一個數據結構,可以通過循環創建一個網站上的導航菜單,每個菜單項可能有一個帶有子菜單項的子菜單。
表中注意的字段是:
內部項目ID
內部父ID
varchar 項目文本
文本項目鏈接
tinyint HasChildren
因此,函數返回數組的示例是:
$menuItems = array( itemID# => array( 'ItemText' => 'Home', 'ItemLink' => 'index.php', 'Children' => array( itemID# => array ( 'ItemText' => 'Home Sub 1', 'ItemLink' => 'somepage.php', 'Children' => 0 ), itemID# => array ( 'ItemText' => 'Home Sub 2', 'ItemLink' => 'somepage2.php', 'Children' => 0 ), ) ), itemID# => array( 'ItemText' => 'Contact', 'ItemLink' => 'contact.php', 'Children' => 0 ) ) );
如果有人能指出我正確的方向來實現這一點,我將不勝感激。 謝謝!
不是太難。 您所做的是將菜單項存儲在一個數組中,您可以在其中通過 ID 查找它們。 然后遍歷菜單項,如果它們的 ParentID 非空,則將它們添加到其父級的子項列表中。 然后從主列表中刪除所有子項,這樣就只剩下頂級項了。
代碼:
<?php
$menuItems = array
(
1 => array
(
'ItemText' => 'Home',
'ItemLink' => 'index.php',
'ParentID' => null,
),
2 => array
(
'ItemText' => 'Home Sub 1',
'ItemLink' => 'somepage.php',
'ParentID' => 1,
),
3 => array
(
'ItemText' => 'Home Sub 2',
'ItemLink' => 'somepage2.php',
'ParentID' => 1,
),
4 => array
(
'ItemText' => 'Contact',
'ItemLink' => 'contact.php',
'ParentID' => null,
),
);
// Each node starts with 0 children
foreach ($menuItems as &$menuItem)
$menuItem['Children'] = array();
// If menu item has ParentID, add it to parent's Children array
foreach ($menuItems as $ID => &$menuItem)
{
if ($menuItem['ParentID'] != null)
$menuItems[$menuItem['ParentID']]['Children'][$ID] = &$menuItem;
}
// Remove children from $menuItems so only top level items remain
foreach (array_keys($menuItems) as $ID)
{
if ($menuItems[$ID]['ParentID'] != null)
unset($menuItems[$ID]);
}
print_r($menuItems);
?>
輸出:
Array
(
[1] => Array
(
[ItemText] => Home
[ItemLink] => index.php
[ParentID] =>
[Children] => Array
(
[2] => Array
(
[ItemText] => Home Sub 1
[ItemLink] => somepage.php
[ParentID] => 1
[Children] => Array
(
)
)
[3] => Array
(
[ItemText] => Home Sub 2
[ItemLink] => somepage2.php
[ParentID] => 1
[Children] => Array
(
)
)
)
)
[4] => Array
(
[ItemText] => Contact
[ItemLink] => contact.php
[ParentID] =>
[Children] => Array
(
)
)
)
有一個每次獲取數組元素時都會調用自身的函數。 如:
調用您的函數以顯示節點。 然后它檢查它調用的節點是否有子菜單,如果有,它再次調用自己。 並且這個過程一直重復,直到它消失,並且所有之前的函數調用都返回。
void printData($mysql_table_node){
if($mysql_table_node.has_node()){
for($i = 0; $i < $mysqql_table_node.num_nodes()){
printData($mysql_table_node->own_node);
}
}
return;
}
您永遠無法知道給定的項目列表中有多少維度。 每個元素可以有一個兒子->孫子->曾孫等等。
因此,您必須使用 遞歸函數來生成多維列表。
<?php
$categories = array(
'1'=> array('name'=>'one','parent'=>null),
'2'=> array('name'=>'two','parent'=>null),
'20'=> array('name'=>'twenty','parent'=>'2'),
'21'=> array('name'=>'twenty one','parent'=>'2'),
'210'=> array('name'=>'two hundred and ten', 'parent'=>'21'),
'211'=> array('name'=>'two hundred and eleven', 'parent'=>'21'),
'212'=> array('name'=>'two hundred and twelve', 'parent'=>'21')
);
$tree=Menu::CreateTree($categories);
print_r($tree);
Menu::GenerateMenuHtmlCode($tree);
class Menu
{
public static function GenerateMenuHtmlCode($tree)
{
echo '<ul>';
foreach ($tree as $key=>$value)
{
echo "<li>".$value['name'];
if(!empty($value['sons']))
self::GenerateMenuHtmlCode($value['sons']);
echo "</li>";
}
echo '</ul>';
}
public static function CreateTree($categories)
{
$tree=array();
self::AddElement(&$categories,&$tree,null);
return $tree;
}
private function AddElement($categories,&$tree,$parent)
{
foreach ($categories as $key=>$value)
{
if($value['parent']==$parent)
{
$tree[$key]=$categories[$key];
$tree[$key]['sons']=array();
self::AddElement($categories,&$tree[$key]['sons'],$key);
}
if(empty($tree['sons'])) unset ($tree['sons']);
}
unset($categories[$parent]);
return ;
}
}
?>
Array
(
[1] => Array
(
[name] => one
[parent] =>
[sons] => Array()
)
[2] => Array
(
[name] => two
[parent] =>
[sons] => Array
(
[20] => Array
(
[name] => twenty
[parent] => 2
[sons] => Array()
)
[21] => Array
(
[name] => twenty one
[parent] => 2
[sons] => Array
(
[210] => Array
(
[name] => two hundred and ten
[parent] => 21
[sons] => Array()
)
[211] => Array
(
[name] => two hundred and eleven
[parent] => 21
[sons] => Array()
)
[212] => Array
(
[name] => two hundred and twelve
[parent] => 21
[sons] => Array()
)
)
)
)
)
)
和:
<ul>
<li>one</li>
<li>two
<ul>
<li>twenty</li>
<li>twenty one
<ul>
<li>two hundred and ten</li>
<li>two hundred and eleven</li>
<li>two hundred and twelve</li>
</ul>
</li>
</ul>
</li>
</ul>
我知道這是一個遲到的回復,但我在上面找到了這個腳本,它太棒了。 我遇到了一個問題,但由於 ItemID 的工作方式,當我使用與 OP 設計類似的表運行它時,它使我的孩子感到不安。 為了解決這個問題,並且考慮到大多數 Web 服務器中的 RAM 量應該能夠處理這個問題,我采用了John Kugelman 的好例子並對其進行了輕微的修改。 我不必將子項應用於所有項目然后在之后取消設置它們,而是創建一個新數組並將其全部構建
代碼:
$new_array = array();
foreach ($menuItems as $key => &$menuItem) {
if (($menuItem['ParentID'] != NULL) && ($menuItem['ParentID'] != '')) {
$new_array[$menuItem['ParentID']]['Children'][$menuItem['ItemID']] = &$menuItem;
} else {
$new_array[$menuItem['ItemID']] = &$menuItem;
}
}
print_r($new_array);
希望這對其他人有所幫助,因為以上內容確實對我有幫助
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.