define() vs const في PHP: أيهما تختار ولماذا هو مهم

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

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

ابدأ الدورة

define() vs const في PHP: معركة العمالقة في تعريف الثوابت

\n\n

هل تساءلت يومًا لماذا يوجد في PHP طريقتان مختلفتان لتعريف الثابت؟ قد يبدو الأمر مكررًا، لكن الفرق بينهما قد يغير بنية كودك بالكامل. هذا السؤال حصد آلاف المشاهدات على Stack Overflow، وليس من دون سبب — فالاختيار بين define() و const يؤثر بشكل كبير على أداء وتصميم تطبيقاتك.

\n\n

اليوم سنحسم الأمر نهائيًا. ستتعرف ليس فقط على الفروقات التركيبية، بل أيضًا على متى يمنحك كل خيار أفضلية حقيقية. هيا بنا!

\n\n

نظرة سريعة: ما هو الثابت في PHP؟

\n\n

الثابت (Constant) هو معرف لقيمة ثابتة لا تتغير أثناء تنفيذ السكربت (على عكس المتغيرات). افتراضيًا، الثوابت حساسة لحالة الأحرف، لكن يمكنك تغيير ذلك (مع define()).

\n\n

مثال على ثابت تقليدي:

\n\n
<?php\ndefine("MAX_UPLOAD_SIZE", 10485760); // 10 ميجابايت بالبايت\necho MAX_UPLOAD_SIZE; // 10485760\n?>
\n\n

نفس المثال مع const:

\n\n
<?php\nconst MAX_UPLOAD_SIZE = 10485760;\necho MAX_UPLOAD_SIZE;\n?>
\n\n

يبدو متطابقًا، لكن دعنا نتعمق أكثر.

\n\n

الفروقات الرئيسية بين define() و const

\n\n

لنوضح الأمور بشكل كامل. إليك الفروقات الأساسية التي يجب أن يعرفها كل مطور PHP.

\n\n

1. وقت التعريف: التجميع (Compilation) مقابل التنفيذ (Runtime)

\n\n

هذا هو الفرق الجوهري.

\n\n
    \n
  • const — يُعرّف في مرحلة التجميع. هذا يعني أنه لا يمكنك استخدام const داخل الحلقات أو الشروط أو الدوال. يجب تعريفه في "جسم" الكلاس (لثوابت الكلاسات) أو في النطاق العام.
  • \n
  • define() — يُنفّذ في وقت التشغيل. يمكنك وضعه في أي مكان: داخل if أو for أو while أو حتى داخل دالة (رغم أنها ممارسة سيئة).
  • \n
\n\n

مثال لن يعمل مع const:

\n\n
<?php\nif (PHP_OS === 'WINNT') {\n    const PLATFORM = 'Windows';\n    // خطأ فادح: لا يمكن استخدام const داخل هيكل تحكم\n}\n?>
\n\n

أما مع define() فالأمر سهل:

\n\n
<?php\nif (PHP_OS === 'WINNT') {\n    define('PLATFORM', 'Windows');\n    echo PLATFORM; // Windows\n}\n?>
\n\n

2. أنواع البيانات: المصفوفات والكائنات

\n\n

لفترة طويلة، كان define() يدعم فقط الأنواع العددية (النصوص، الأرقام، القيم المنطقية). منذ PHP 7، أصبح define() يدعم المصفوفات.

\n\n

const يدعم المصفوفات أيضًا (منذ PHP 5.6)، لكنه لا يدعم الكائنات أو التعبيرات:

\n\n
<?php\n// يعمل مع PHP 7+\ndefine('FRUITS', ['تفاح', 'موز', 'كرز']);\necho FRUITS[1]; // موز\n\n// يعمل أيضًا (PHP 5.6+)\nconst COLORS = ['أحمر', 'أخضر', 'أزرق'];\n\n// لكن هذا سيؤدي لخطأ!\n// const RESULT = 2 + 3; // يعمل، هذا تعبير ثابت\n// const DYNAMIC = rand(1, 10); // خطأ! ليس تعبيرًا ثابتًا\n?>
\n\n

ملاحظة مهمة: define() يمكنه استخدام نتائج الدوال (define('SITE_NAME', get_site_name()))، بينما const يقبل فقط التعبيرات الثابتة (أرقام، نصوص، ثوابت أخرى).

\n\n

3. مساحة الأسماء (Namespace) ونطاق الرؤية

\n\n

هناك فارق دقيق لكنه مهم.

\n\n
    \n
  • define() — يُنشئ دائمًا ثابتًا عامًا. حتى لو استخدمته داخل مساحة اسم، سيظل الثابت متاحًا من أي مكان.
  • \n
  • const — يخضع لقواعد مساحة الأسماء. الثابت المُعرّف في namespace MyApp\\Config سيُسمى MyApp\\Config\\SITE_NAME.
  • \n
\n\n

مثال توضيحي:

\n\n
<?php\nnamespace MyApp\\Config;\n\n// هذا سيُعرّف الثابت في النطاق العام\n// define('DB_HOST', 'localhost');\n\n// هذا سيُعرّف الثابت داخل مساحة الاسم MyApp\\Config\nconst DB_HOST = 'localhost';\n\necho DB_HOST; // localhost\necho \\MyApp\\Config\\DB_HOST; // localhost (الوصول الكامل)\n?>
\n\n

متى تستخدم define() ومتى تستخدم const؟

\n\n

إليك دليل سريع لاتخاذ القرار الصحيح:

\n\n
    \n
  • استخدم const عندما:\n
      \n
    • تحتاج ثوابت خاصة بكلاس (class constants).
    • \n
    • تريد ثوابت ضمن مساحة اسم محددة.
    • \n
    • تريد أداءً أفضل (const أسرع قليلاً).
    • \n
    • تعمل مع قيم ثابتة لا تتغير.
    • \n
    \n
  • \n
  • استخدم define() عندما:\n
      \n
    • تحتاج تعريف ثابت بناءً على شرط (مثل if).
    • \n
    • تريد استخدام تعبيرات ديناميكية (مثل نتائج دوال).
    • \n
    • تحتاج ثوابت عامة متاحة من أي مكان.
    • \n
    • تعمل مع مصفوفات كبيرة أو بيانات معقدة.
    • \n
    \n
  • \n
\n\n

الخلاصة: أيهما أفضل؟

\n\n

لا توجد إجابة واحدة تناسب الجميع. const مثالي للثوابت الثابتة داخل الكلاسات ومساحات الأسماء، بينما define() يوفر مرونة أكبر للثوابت العامة والديناميكية. القاعدة الذهبية: استخدم const افتراضيًا، وانتقل إلى define() فقط عندما تحتاج مرونته.

\n\n

هل لديك تجربة مع أحد هذين الأسلوبين؟ شاركنا في التعليقات!

المدونات

توصيات الكتب