كيفية التحقق مما إذا كانت المصفوفة ترابطية أم متسلسلة في PHP: تحليل أشهر الأخطاء
\n\nهل سبق لك أن كتبت foreach وحصلت على نتيجة غير متوقعة؟ أو ربما مررت مصفوفة إلى دالة كانت تنتظر قائمة، لكنها استقبلت مصفوفة ترابطية بمفاتيح نصية؟ إذا كان الأمر كذلك، فأنت لست وحدك. سؤال «How to check if PHP array is associative or sequential?» هو من بين الأسئلة الأكثر شيوعًا على Stack Overflow بآلاف المشاهدات. وهذا ليس من قبيل الصدفة: الخلط بين أنواع المصفوفات هو أحد أكبر الأخطاء التي يقع فيها مطورو PHP.
في هذه المقالة، سنشرح الفرق بين المصفوفات الترابطية والمتسلسلة (sequential)، ونعرض الأخطاء الشائعة، ونقدم حلولًا عملية. هيا بنا!
\n\nما هي المصفوفة المتسلسلة والترابطية؟
\n\nفي PHP، لا يوجد تقسيم صارم بين «القوائم» و«القواميس» كما في Python أو JavaScript. نوع واحد — array — يمكن أن يكون كليهما. لكن من الناحية العملية، من المهم فهم الفرق:
- \n
- المصفوفة المتسلسلة (sequential) — المفاتيح مرتبة: 0، 1، 2، 3... بدون فجوات. مثال:
['تفاحة', 'كمثرى', 'كرز']. \n - المصفوفة الترابطية (associative) — المفاتيح عبارة عن نصوص أو أرقام غير مرتبة. مثال:
['name' => 'أحمد', 'age' => 30]. \n
قد يبدو الأمر بسيطًا. لكن في الواقع، يخطئ المطورون غالبًا عند محاولة تحديد نوع المصفوفة يدويًا. دعنا نستعرض أشهر هذه الأخطاء.
\n\nالخطأ الشائع رقم 1: استخدام array_keys() والمقارنة مع range
\n\nأحد أكثر الأساليب شيوعًا هو أخذ مفاتيح المصفوفة، وإنشاء تسلسل من 0 إلى count($array)-1، ثم المقارنة. يبدو منطقيًا، لكن هناك تفاصيل دقيقة.
// مثال على نهج خاطئ\nfunction isSequential($arr) {\n return array_keys($arr) === range(0, count($arr) - 1);\n}\n\n$test = ['a', 'b', 'c'];\nvar_dump(isSequential($test)); // true — صحيح\n\n$test2 = ['x' => 1, 'y' => 2];\nvar_dump(isSequential($test2)); // false — صحيح\n\n$test3 = [0 => 'a', 2 => 'b'];\nvar_dump(isSequential($test3)); // false — صحيح\n\n$test4 = ['0' => 'a', '1' => 'b'];\nvar_dump(isSequential($test4)); // ??? \n\n\nالمشكلة هي أن PHP تقوم تلقائيًا بتحويل المفاتيح النصية إلى أعداد صحيحة إذا كانت تبدو كأرقام. ['0' => 'a', '1' => 'b'] هي في الواقع مصفوفة متسلسلة، لكن الدالة قد تعطي نتيجة غير متوقعة بسبب المقارنة الصارمة (===).
الخلاصة: هذا الأسلوب يعمل، لكن فقط إذا كنت متأكدًا من أنواع المفاتيح. للإنتاج، من الأفضل استخدام طرق أكثر موثوقية.
\n\nالخطأ الشائع رقم 2: التحقق من المفتاح الأول فقط
\n\nبعض المطورين يعتقدون: «إذا كان المفتاح الأول هو 0، فالمصفوفة متسلسلة». هذا اعتقاد خاطئ وخطير.
\n\nfunction isSequentialByFirstKey($arr) {\n if (empty($arr)) return true;\n return array_key_first($arr) === 0;\n}\n\n$bad = [0 => 'a', 'name' => 'أحمد'];\nvar_dump(isSequentialByFirstKey($bad)); // true — ولكن يجب أن تكون false!\n\n\nالمفتاح الأول هو 0، لكن المصفوفة ترابطية بوضوح. هذا الفحص سيتجاهل المصفوفات المختلطة التي تظهر غالبًا في المشاريع الحقيقية.
\n\nالخلاصة: لا تحكم على المصفوفة من خلال العنصر الأول فقط. افحص جميع المفاتيح.
\n\nالخطأ الشائع رقم 3: تجاهل المصفوفات الفارغة
\n\nالمصفوفة الفارغة [] — هل هي متسلسلة وترابطية في نفس الوقت؟ من وجهة نظر PHP — نعم. لكن بعض الدوال تتعطل.
function isAssociative($arr) {\n return count(array_filter(array_keys($arr), 'is_string')) > 0;\n}\n\nvar_dump(isAssociative([])); // false — المصفوفة الفارغة ليست ترابطية\nvar_dump(isAssociative([1, 2, 3])); // false — صحيح\n\n\nيبدو منطقيًا، لكن إذا كنت تتوقع أن الدالة سترجع true للمصفوفة الفارغة (كما لو كانت ترابطية)، فأنت مخطئ. المصفوفة الفارغة هي حالة خاصة.