Elvis حي: مقارنة بين العامل الثلاثي المختصر والعامل الفارغ في PHP

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

من هو إلفيس وما علاقته بـ PHP؟

\n\n

إذا كنت قد كتبت أي كود PHP من قبل، فمن المحتمل أنك رأيت تركيبات غريبة في كود الآخرين: $name ?: 'ضيف' أو $name ?? 'ضيف'. للوهلة الأولى، يبدوان متطابقين. لكن في الواقع، وراء هذين العاملين تختبئ آليات مختلفة تمامًا يمكنها إما إنقاذ كودك أو التسبب في مشاكل.

\n\n

على Stack Overflow، جمع سؤال "عامل PHP الثلاثي المختصر ("Elvis") مقابل العامل الفارغ" عشرات الآلاف من المشاهدات. وهذا ليس من قبيل الصدفة. يختلط الأمر على المطورين، ويخطئون، ثم يقضون وقتًا طويلاً في البحث عن الأخطاء. دعونا نفهم الأمر مرة واحدة وإلى الأبد، ونتوقف عن التخمين.

\n\n

في هذه المقالة، لن نقوم فقط بسرد الاختلافات. سننظر تحت غطاء PHP، ونرى حالات حقيقية من بيئات الإنتاج، ونفهم متى نستخدم أي عامل. هيا بنا!

\n\n

نبذة تعريفية سريعة: ما هذا بحق الجحيم؟

\n\n

العامل الثلاثي (التقليدي)

\n

في البداية، دعنا نتذكر الأساسيات. العامل الثلاثي هو صيغة مختصرة لـ if-else:

\n\n
$age = 20;\n$status = ($age >= 18) ? 'بالغ' : 'طفل';\n// $status = 'بالغ'
\n\n

الأمر بسيط: إذا كان الشرط صحيحًا، نأخذ القيمة الأولى، وإلا نأخذ الثانية.

\n\n

العامل الثلاثي المختصر (المعروف أيضًا باسم عامل Elvis) — ?:

\n

هذا اختصار للحالة التي تتحقق فيها من "صحة" متغير وتريد استخدام قيمته نفسها:

\n\n
$name = 'أليكسي';\n$greeting = $name ?: 'ضيف';\n// $greeting = 'أليكسي'\n\n$name = '';\n$greeting = $name ?: 'ضيف';\n// $greeting = 'ضيف'
\n\n

يعمل كالتالي: إذا تم تحويل $name إلى true، نأخذ $name. وإلا، نأخذ "ضيف".

\n\n

العامل الفارغ — ??

\n

ظهر في PHP 7.0 وأصبح على الفور المفضل لدى المطورين:

\n\n
$name = 'أليكسي';\n$greeting = $name ?? 'ضيف';\n// $greeting = 'أليكسي'\n\n$name = null;\n$greeting = $name ?? 'ضيف';\n// $greeting = 'ضيف'
\n\n

الفرق عن إلفيس: التحقق يكون فقط من null، وليس من "الخطأ" بشكل عام.

\n\n

الفرق الرئيسي: ما الذي يعتبر "فارغًا"؟

\n\n

هنا يبدأ الجزء المثير للاهتمام. دعونا نلقي نظرة على جدول مقارنة لقيم مختلفة لـ $value:

\n\n
$value = false;\necho $value ?: 'افتراضي'; // 'افتراضي' (false هي "خطأ")\necho $value ?? 'افتراضي'; // false (false ليست null)\n\n$value = 0;\necho $value ?: 'افتراضي'; // 'افتراضي' (0 هي "خطأ")\necho $value ?? 'افتراضي'; // 0 (0 ليست null)\n\n$value = '';\necho $value ?: 'افتراضي'; // 'افتراضي' (سلسلة فارغة هي "خطأ")\necho $value ?? 'افتراضي'; // '' (سلسلة فارغة ليست null)\n\n$value = [];\necho $value ?: 'افتراضي'; // 'افتراضي' (مصفوفة فارغة هي "خطأ")\necho $value ?? 'افتراضي'; // [] (مصفوفة فارغة ليست null)\n\n$value = '0';\necho $value ?: 'افتراضي'; // 'افتراضي' (السلسلة "0" هي "خطأ"!)\necho $value ?? 'افتراضي'; // '0' (السلسلة "0" ليست null)
\n\n

هل ترى الفرق؟ إلفيس يعمل كتحقق من "الصحة" (truthy/falsy)، بينما العامل الفارغ هو تحقق صارم من الوجود والاختلاف عن null.

\n\n

تحت الغطاء: كيف يعمل هذا على مستوى المحرك

\n\n

دعونا نلقي نظرة على شفرة مصدر PHP (تقريبًا). إذا كنت قد قمت بتجميع PHP من المصدر من قبل، فأنت تعلم أن كلا العاملين يتم معالجتهما في مرحلة التحليل (parsing).

\n\n

العامل الثلاثي المختصر (?):

\n

في الواقع، هذا سكر نحوي (syntactic sugar). $a ?: $b يتحول إلى $a ? $a : $b. لكن هناك فارق بسيط: PHP لا تحسب $a مرتين. إنها تحفظ النتيجة في متغير مؤقت. هذا مهم للدوال ذات التأثيرات الجانبية:

\n\n
function getData() {\n    echo "تم استدعاء الدالة!\\n";\n    return rand(0, 1) ? 'data' : '';\n}\n\n// إلفيس سيستدعي الدالة مرة واحدة\n$result = getData() ?: 'افتراضي';\n// "تم استدعاء الدالة!" — مرة واحدة
\n\n

إذا كانت PHP ستحسب $a مرتين،

المدونات

توصيات الكتب