بعد اسبوع من التعب, تمكنت عرض الشجري لقائمة مسطحة , كيف يمكنني ان احسن من الكود ؟
إذا كان ما أتذكره صحيح من مادة البرمجة، دالتك جدا مكلفة من ناحية السيطرة على الذاكرة. في كل مرة تستدعي فيها الدالة، فإنك ترسل لها $data بشكل كامل، أي إذا استدعيتها 10 مرات بواسطة الـ recursive، ستكون هناك 10 نسخ من $data في الذاكرة، و هذا مكلف و يمكن تحسينه بواسطة استخدام global، كما ذكر في [1]
هذا أولاـ ثانيا، في كل مرة تستدعي فيها الدالة، فإنك تمر على جميع عناصر $data و هذا يسبب بطء لا داعي منه. حبذا لو تستخدم الـ Hash أو Associative Array لأنه أسرع [2]
هذه محاولة من عندي، علما لم أقم بتجربتها، عليك بمقارنة ما كتبته أنا (طبعا بعد أن تقوم أنت بتصحيحه :) ) و ما كتبته أنت
function generateTree() {
global $data;
$count = count($data);
$tree = array();
for ( $i = 0; i < $count; $i++ ) {
$row = $data[$count];
$id = $row['category_ID'];
$name = $row['category_Name'];
$parent = $row['category_Parent'];
$tree[$id]['name'] = $name;
$tree[$id]['children'] = array();
if ( $parent ) {
$tree[$parent]['children'][$id] = $name;
}
}
return $tree;
}
function printTree($id) {
global $tree;
$node = $tree[$id];
$output = '<ul><li>' . $node['name'];
foreach( $node['children'] as $child_id => $child_name ) {
printTree($child['id']);
}
$output .= '</li></ul>';
}
$tree = generateTree();
printTree(1);
أول دالة، تقوم بإنشاء associative array بالمرور مرة واحدة فقط على جميع عناصر $data. الـ associative array شكلها مثل الشجرة، كل node تحمل ID عنصر. كما تحوي على اسم الـ category و قائمة بـ IDs الأطفال.
الدالة الثانية، استدعها و أرسل لها قيمة أصغر و أول عنصر، مثلا 1، و ستقوم بجلب كل عنصر مرة واحدة فقط.
ملحوظة: ستواجه مشاكل لو $data ليست مرتبة حسب category_parent
ملحوظة أخرى: لم أستخدم PHP من زمان، فاعذرني على الأخطاء :)
[1]
[2]
لم أكن في كامل وعيي بالأمس ^^، لكن دالة printTree لا ترسل لها قيمة أول عنصر، بل ترسل لها قيمة العناصر التي لا parent لها.
اعذرني على الخطأ
شكرا لأخذك الوقت لكتابة الرد و الكود ,
و من الجيد انك لفت نظري لل$data , لانني لاحضت بطئء عند تحميل الصفحة
لكن دالة printTree لا ترسل لها قيمة أول عنصر، بل ترسل لها قيمة العناصر التي لا parent لها.
اي العناصر ذوات category_parent = 0 , صحيح ؟
صحيح. سينتج معك شئ قريب من (هذا pseudocode )
$rows = $mysqli->query("SELECT id from category where category_parent = 0");
for ( $row in $rows ) {
printTree($row);
}
ستواجه مشاكل لو $data ليست مرتبة حسب category_parent
استخدمت هذا الحل SELECT * FROM categories ORDER BY categorie_Parent,categorie_ID
هذه الطريقة السليمة. آسف لكن مصاب باحتقان و لم أنم كفاية :). اعذرني لو نسيت أحد التفاصيل. ما شاء الله عليك وجدت النقص :)
لكن لا أتوقع توجد حاجة لاسترجاع جميع محتويات الجدول، فقط category_id و مرتبة حسب category_parent. لأن الـ $tree فيها الأسماء محفوظة فلا داعي لأخذ حيز إضافي فيه نفس المعلومات :)
عذرا ولكن لدي سؤال اضافي ,
و لكن في الكود الاول من اين حصلنا على متغيرات $node['children'] , $child_id , $child_name ,
يتم تعريف $tree خارج نطاق الدالة
$tree = generateTree();
و من ثم استخدامها في printTree بواسطة global. و node['children'] تم تعريفها في
$tree[$id]['children'] = array();
و إضافة العناصر في
if ( $parent ) {
$tree[$parent]['children'][$id] = $name;
}
الـ node المعرفة في الدالة الثانية عبارة عن Associative array و تحوي keys = (name, children) بحيث قيمة المفتاح name هو اسم الـ category و children عبارة عن associative array داخلية فيها الأولاد، و هيه node['children']. و للمرور بكل عناصر الـ Array استخدمت foreach بحيث أن الـ Key يمثل الـ child[id] و القيمة تمثل الاسم child['name']
أتمنى أكون وضحتها لك بشكل مناسب. سأحاول لاحقا بعد العمل أن أقوم بشرحها بطريقة أخرى. لكن لم تقل لي، هل طبقتها :)؟
ليست موجودة في قاعدة البيانات، لكن يتم إنشائها في الكود التالي:
$tree[$id]['children'] = array();
if ( $parent ) {
$tree[$parent]['children'][$id] = $name;
}
ببساطة، إذا كان للصف قيمة للـ parent غير الصفر (الصفر يعادله false)، السطر هذا
$tree[$parent]['children'][$id] = $name;
يقوم بالذهاب إلى حقل الـ parent و يضيف له الصف الحالي كـ child. في النهاية كل عنصر سيُربط بأطفاله.
التعليقات