16

إذا كان ما أتذكره صحيح من مادة البرمجة، دالتك جدا مكلفة من ناحية السيطرة على الذاكرة. في كل مرة تستدعي فيها الدالة، فإنك ترسل لها $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] http://www.php.net/manual/en/language.variables.scope.php

[2] http://stackoverflow.com/questions/2473989/list-of-big-o-for-php-functions

لم أكن في كامل وعيي بالأمس ^^، لكن دالة 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']

أتمنى أكون وضحتها لك بشكل مناسب. سأحاول لاحقا بعد العمل أن أقوم بشرحها بطريقة أخرى. لكن لم تقل لي، هل طبقتها :)؟

عفوا , ولكن لم تفهم قصدي ,

children غير موجودة في القاعدة البيانات , فمن اين تم استدعائها ؟

ليست موجودة في قاعدة البيانات، لكن يتم إنشائها في الكود التالي:

    $tree[$id]['children'] = array();

    if ( $parent ) {
        $tree[$parent]['children'][$id] = $name;
    }

ببساطة، إذا كان للصف قيمة للـ parent غير الصفر (الصفر يعادله false)، السطر هذا

        $tree[$parent]['children'][$id] = $name;

يقوم بالذهاب إلى حقل الـ parent و يضيف له الصف الحالي كـ child. في النهاية كل عنصر سيُربط بأطفاله.

برمجة

المواضيع والنقاشات المتعلقة بالبرمجة بشكل عام او لغات البرمجة التي لايوجد لها مجتمعات فرعية.

16.3 ألف متابع