[英]Organizing mySQL data using recursive PHP
我正在為客戶創建一個問卷,該問卷要求問題按3個層次進行組織。 我已經成功創建了UI,但是最近3個小時我一直在嘗試從數據庫中提取數據,以便將所有內容加載到正確的位置。 該數據庫是由客戶端組織的,因此我無法控制它:
id description parentId about
1 Level 1 0 This is the top level or in my case tab1
2 Level 2 0 This is the next tab in the top level
3 Level 1a 1 This is the first category under tab1
4 Level 1b 1 This is the next category under tab1
5 Level 1a1 3 This is the content under the first category of tab1
因此,parentId為0的所有內容都是最高級別,並且將會包含parentId為1的第二個級別的內容,依此類推。 令人困惑的是,我幾乎無法理解這一點,但這就是我被告知要這樣做的方式。
什么方法是執行這樣的最佳方法? 下面附有我正在用作參考的另一個問題的示例(盡管不起作用)
foreach (mysql_query("SELECT * FROM pB_test ORDER BY id ASC") as $row) {
$menuitem = array_merge(array(), $row);
$menuLookup[$menuitem['id']] = $menuitem;
if ($menuitem['parent'] == null) {
$menuitem['path'] = "/" . $menuitem['name'];
$menu[] = $menuitem[];
} else {
$parent = $menuLookup[$menuitem['parent']];
$menuitem['path'] = $parent['path'] . "/" . $menuitem['name'];
$parent['menu'][] = $menuitem;
}
}
任何幫助將不勝感激。 干杯
如果您正好有3個級別,則可以嘗試以下方法:
http://sqlfiddle.com/#!2/70e96/16
(
SELECT 1 AS lvl,
top_level.description AS o1, top_level.id AS id1,
NULL AS o2, NULL AS id2,
NULL AS o3, NULL AS id3,
top_level.*
FROM node AS top_level
WHERE top_level.parentId = 0
)UNION ALL(
SELECT 2 AS lvl,
top_level.description AS o1, top_level.id AS id1,
category_level.description AS o2, category_level.id AS id2,
NULL AS o3, NULL AS id3,
category_level.*
FROM node AS top_level
INNER JOIN node AS category_level ON category_level.parentId = top_level.id
WHERE top_level.parentId = 0
)UNION ALL(
SELECT 3 AS lvl,
top_level.description AS o1, top_level.id AS id1,
category_level.description AS o2, category_level.id AS id2,
last_level.description AS o3, last_level.id AS id3,
last_level.*
FROM node AS top_level
INNER JOIN node AS category_level ON category_level.parentId = top_level.id
INNER JOIN node AS last_level ON last_level.parentId = category_level.id
WHERE top_level.parentId = 0
)
ORDER BY o1,o2,o3;
我為選擇添加了一個lvl
字段,每個級別都有不同的值。 還添加了o1,o2,o3以便更好地訂購嵌套級別,當然您可能還有其他需求。 您可以處理PHP中的所有行,例如將它們分成3個數組(每個級別一個),或者按ID創建查找表,等等。
我也有同樣的問題,但是經過大量的搜索和堆棧溢出:-)我找到了答案。...這是我的編碼方式。
function showComments($parent = 0)
{
$commentQuery = "SELECT * FROM comment WHERE parent = ".mysql_real_escape_string($parentId);
$commentResult = mysql_query($commentQuery)
while ($row = mysql_fetch_array($commentResult))
{
echo '[Table containing comment data]';
showComments($row['commentID']);
}
}
showComments();
如果要使用外部數據庫,則可能需要用PHP而不是SQL來做到這一點。 我尚未對以下各項進行基准測試,因此請嘗試使用您的數據,看看性能是否有問題。
您可以選擇自己處理孤立記錄(該記錄引用不再存在的parentID)。
以這種方式在PHP中進行排序要求您事先擁有所有數據,因此請使用PDO的fetchAll(PDO::FETCH_ASSOC)
方法之類的方法,這將導致如下所示的結果:
$data_from_database = array(
array("id" => 1, "parentId" => 0, "description" => "Level 1"),
array("id" => 2, "parentId" => 1, "description" => "Level 1a"),
array("id" => 3, "parentId" => 1, "description" => "Level 1b"),
array("id" => 4, "parentId" => 0, "description" => "Level 2"),
array("id" => 5, "parentId" => 2, "description" => "Level 1a1"),
array("id" => 6, "parentId" => 5, "description" => "Level 1a11a"),
array("id" => 7, "parentId" => 5, "description" => "Level 1a11b"),
array("id" => 8, "parentId" => 9, "description" => "Level 3"),
);
首先,您需要將主鍵(ID)作為陣列的鍵。 以下還將鍵“ children”和“ is_orphan”添加到每個記錄。
$data_by_id = array();
foreach($data_from_database as $row)
$data_by_id[$row["id"]] = $row + array(
"children" => array(),
"is_orphan" => false
);
看起來像這樣:
$data_from_database = array(
1 => array("id" => 1, "parentId" => 0, "description" => "Level 1",
"children" => array(), "is_orphan" => false),
...
);
現在,它變得棘手:我們將遍歷數組並添加引用。
foreach($data_by_id as &$row)
{
if($row["parentId"] > 0)
{
if(isset($data_by_id[$row["parentId"]]))
$data_by_id[$row["parentId"]]["children"][] = &$row;
else
$row["is_orphan"] = true;
}
}
unset($row); // Clear reference (important).
最后一步是清理陣列的“根”。 它將包含對重復行的引用。
foreach($data_by_id as $id => $row)
{
// If you use this option, you'll remove
// orphaned records.
#if($row["parentId"] > 0)
# unset($data_by_id[$id]);
// Use this to keep orphans:
if($row["parentId"] > 0 AND !$row["is_orphan"])
unset($data_by_id[$id]);
}
在每個步驟之后使用print_r($data_by_id)
看看會發生什么。
如果證明這是一項耗時的操作,請嘗試僅通過執行SELECT id, parentId FROM ...
來構建樹,然后再獲取諸如description
的元數據。 您也可以將結果存儲在Memcache中或序列化到數據庫中。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.