لماذا يعتبر ترتيب المصفوفات الترابطية تحديًا (وكيفية حله)
\n\nتخيل أنك استخرجت قائمة بالمستخدمين من قاعدة البيانات. كل مستخدم لديه اسم، عمر، مدينة، وتقييم. البيانات جاءت على شكل مصفوفة من المصفوفات الترابطية. وفجأة يقول لك المدير: "رتبهم حسب العمر، ثم حسب التقييم بترتيب تنازلي". موقف مألوف، أليس كذلك؟ إذا كنت قد كتبت كودًا بلغة PHP من قبل، فبالتأكيد واجهت هذه المهمة: sort an array of associative arrays by column value. هذا السؤال الذي حصد آلاف المشاهدات على Stack Overflow ليس مبالغًا فيه - إنه حجر عثرة حقيقي للعديد من المطورين.
\n\nفي هذه المقالة، سنستعرض جميع طرق ترتيب المصفوفات متعددة الأبعاد في PHP. بدءًا من الدالة البسيطة usort وصولاً إلى الدالة القوية array_multisort. ستتعلم كيفية الترتيب حسب حقل واحد، حسب عدة حقول، باتجاهات مختلفة، وكيف تتجنب الأخطاء الشائعة المتعلقة بأنواع البيانات. هيا بنا!
المشكلة: لماذا لا تعمل الدالة sort() العادية
\n\nلنفترض أن لدينا المصفوفة التالية:
\n\n<?php\n$users = [\n ['name' => 'أحمد', 'age' => 25, 'rating' => 4.7],\n ['name' => 'سارة', 'age' => 30, 'rating' => 3.9],\n ['name' => 'مريم', 'age' => 22, 'rating' => 4.9],\n];\n?>\n\nإذا جربت استخدام sort($users)، فسيصدر PHP تحذيرًا وسيبقي المصفوفة كما هي. لماذا؟ لأن sort() تقارن العناصر مباشرة، ولا تعرف PHP كيفية مقارنة المصفوفات الترابطية. إنها تحتاج إلى توجيه - أي حقل يجب اعتباره معيارًا للترتيب.
الطريقة الأولى: usort() - ملك الترتيب المخصص
\n\nالدالة usort() تأخذ مصفوفة ودالة رد اتصال (callback) تقارن بين عنصرين. هذه هي الطريقة الأكثر مرونة والأكثر استخدامًا.
الترتيب حسب حقل واحد (تصاعديًا)
\n\n<?php\nusort($users, function($a, $b) {\n return $a['age'] <=> $b['age'];\n});\n// النتيجة: مريم (22), أحمد (25), سارة (30)\n?>\n\nعامل المقارنة <=> (السفينة الفضائية) ظهر في PHP 7 ويجعل الكود أنظف. يُرجع -1 أو 0 أو 1 بناءً على المقارنة. إذا كنت تريد ترتيبًا تنازليًا، فقط بدّل مكان $a و $b:
<?php\nusort($users, function($a, $b) {\n return $b['age'] <=> $a['age'];\n});\n// النتيجة: سارة (30), أحمد (25), مريم (22)\n?>\n\nالترتيب حسب حقل نصي
\n\nمع النصوص، الأمر يعمل بنفس الطريقة، لكن من المهم تذكر إعدادات اللغة المحلية. إذا كنت ترتب أسماء عربية، استخدم setlocale() و strcoll() للمعالجة الصحيحة:
<?php\nsetlocale(LC_ALL, 'ar_SA.UTF-8');\nusort($users, function($a, $b) {\n return strcoll($a['name'], $b['name']);\n});\n?>\n\nالطريقة الثانية: array_multisort() - للترتيب حسب عدة أعمدة
\n\nعندما تحتاج إلى الترتيب أولاً حسب حقل ثم حسب حقل آخر (مثلًا حسب المدينة، وداخل المدينة حسب العمر)، تبدأ usort في طلب منطق معقد. هنا يأتي دور array_multisort().
الترتيب حسب حقلين
\n\n<?php\n$ages = array_column($users, 'age');\n$ratings = array_column($users, 'rating');\narray_multisort($ages, SORT_ASC, $ratings, SORT_DESC, $users);\n?>\n\nدعنا نشرح السحر: نقوم بإنشاء مصفوفات منفصلة من الأعمدة المطلوبة، ثم نمررها إلى array_multisort. مهم: المصفوفة الأصلية تُمرر كآخر معامل - سيتم إعادة ترتيبها وفقًا لترتيب المصفوفات الأولى. هذه أداة قوية ولكنها خطيرة: إذا كانت الأعمدة بأطوال مختلفة، ستحصل على خطأ.
الطريقة الثالثة: array_column() + sort() - خدعة للسطر الواحد
\n\nإذا كنت تحتاج فقط إلى ترتيب مصفوفة حسب حقل رقمي واحد، يمكنك استخدام مزيج من array_column() و array_multisort() في سطر واحد:
<?php\narray_multisort(array_column($users, 'age'), SORT_ASC, $users);\n?>