การ query และการจัดการแสดงผลในรูปแบบ tree
มีคำถามบน Facebook เกี่ยวกับการ query และ แสดงผลในแบบ tree โดยมีรูปแบบข้อมูลที่จัดเก็บตามรูป
หลักเกณฑ์ก็คือ parent_id จะทำการเก็บ id ของรายการที่ระดับที่สูงกว่า ซึ่งโจทย์สามารถมีระดับลูกได้แบบไม่จำกัด
แนวคิดจริงๆผมแนะนำให้ทำการ query ในแต่ละระดับออกมาแสดงผล เช่นในครั้งแรกเราจะ query เอาเฉพาะที่ parent_id เป็น 0 ออกมาแสดงก่อน เพราะมันคือระดับแรกสุด จากนั้นเมื่อมีการคลิกที่แต่ละรายการค่อยไปโหลดเอารายการที่มี parent_id ตรงกับรายการที่คลิกมาแสดงผล ซึ่งเป็นวิธีที่มีประสิทธิภาพที่สุด เนื่องจากหากมีข้อมูลจำนวนมาก การพยายาม query รายการทั้งหมดมาแสดงอาจสาหัสก็ได้
แต่เนื่องจากโจทย์ต้องการ query ข้อมูลออกมาทั้งหมด ผมเลยแนะนำวิธีข้างล่างนี้ครับ
วิธีคิดในการ query แบบนี้คือการ query ข้อมูลทั้งหมดออกมาเลยครั้งเดียว (เหมาะกับข้อมูลที่มีจำนวนไม่มาก) โดยเรียงลำดับตาม id และ parent_id หลังจากนั้น ก็เอาข้อมูลทั้งหมดมาใส่ array $datas แล้วค่อยเอามาแสดงผลอีกที โดยที่ตัวอย่างนี้ผมใช้ตัวแปร pointer เก็บข้อมูลรายการต่างๆเพื่อใช้ในการอ้างอิง รายการในระดับที่สูงกว่า
หลักเกณฑ์ก็คือ parent_id จะทำการเก็บ id ของรายการที่ระดับที่สูงกว่า ซึ่งโจทย์สามารถมีระดับลูกได้แบบไม่จำกัด
แนวคิดจริงๆผมแนะนำให้ทำการ query ในแต่ละระดับออกมาแสดงผล เช่นในครั้งแรกเราจะ query เอาเฉพาะที่ parent_id เป็น 0 ออกมาแสดงก่อน เพราะมันคือระดับแรกสุด จากนั้นเมื่อมีการคลิกที่แต่ละรายการค่อยไปโหลดเอารายการที่มี parent_id ตรงกับรายการที่คลิกมาแสดงผล ซึ่งเป็นวิธีที่มีประสิทธิภาพที่สุด เนื่องจากหากมีข้อมูลจำนวนมาก การพยายาม query รายการทั้งหมดมาแสดงอาจสาหัสก็ได้
แต่เนื่องจากโจทย์ต้องการ query ข้อมูลออกมาทั้งหมด ผมเลยแนะนำวิธีข้างล่างนี้ครับ
$datas = array();
$pointer = array();
$sql = "SELECT `id`,`parent_id`,`name` FROM `test` ORDER BY `id`,`parent_id`";
foreach ($db->customQuery($sql) AS $item) {
if ($item['parent_id'] == 0) {
// รายการระดับแรก
$datas[$item['id']] = $item;
// ใช้ตัวแปร pointer เก็บตำแหน่งตาม id
$pointer[$item['id']] = &$datas[$item['id']];
} else {
// รายการลูกจะเพิ่มไปที่ pointer ของระดับก่อนหน้า
$pointer[$item['parent_id']]['childs'][$item['id']] = $item;
$pointer[$item['id']] = &$pointer[$item['parent_id']]['childs'][$item['id']];
}
}
// print_r($datas); // ตรวจสอบผลลัพท์
// วนลูปเพื่อแสดงผลรายการระดับแรก
foreach ($datas AS $values) {
show_result($values, 0);
}
// ฟังก์ชั่นจัดการแสดงผล
function show_result($datas, $level) {
// แสดงผล
echo str_repeat(' ', $level).$datas['name'].'<br>';
if (isset($datas['childs'])) {
foreach ($datas['childs'] AS $values) {
show_result($values, $level + 1);
}
}
}
วิธีคิดในการ query แบบนี้คือการ query ข้อมูลทั้งหมดออกมาเลยครั้งเดียว (เหมาะกับข้อมูลที่มีจำนวนไม่มาก) โดยเรียงลำดับตาม id และ parent_id หลังจากนั้น ก็เอาข้อมูลทั้งหมดมาใส่ array $datas แล้วค่อยเอามาแสดงผลอีกที โดยที่ตัวอย่างนี้ผมใช้ตัวแปร pointer เก็บข้อมูลรายการต่างๆเพื่อใช้ในการอ้างอิง รายการในระดับที่สูงกว่า
ผลลัพท์
one
four
six
seven
five
two
three
eight
nine
ten