الثوابت في PHP

من موسوعة حسوب
< PHP

الثابت هو معرّف (اسم) لقيمة بسيطة، وكما هو واضح من الاسم فإنّ هذه القيمة غير قابلة للتبديل أثناء تنفيذ الشيفرة (باستثناء الثوابت السحرية والتي لا تعدّ ثوابت في الواقع). الثابت حساس لحالة الأحرف ومن الشائع استخدام الأحرف الكبيرة في تسمية الثوابت.

تتبع الثوابت نفس القواعد المتّبعة للتسمية في PHP، فاسم الثابت الصحيح يبدأ بحرف أو بشرطة سفلية، متبوعًا بعدد غير محدّد من الأحرف والأرقام والشرطات السفلية. ولو أردنا استخدام التعابير النمطية (Regular Expressions) للتعبير عن اسم المتغير فسيكون كالتالي:

[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*

نصيحة: راجع دليل Userland للتسمية.

المثال 1: أسماء ثوابت صحيحة وغير صحيحة

<?php
// أسماء ثوابت صحيحة
define("FOO",     "something");
define("FOO2",    "something else");
define("FOO_BAR", "something more");

// أسماء ثوابت صحيحة
define("2FOO",    "something");

// هذه الطريقة صحيحة ولكن تجنّب استخدامها	
// إذ قد تقدّم اللغة يومًا ما ثابتًا سحريًا
// قد يؤدي إلى تعطيل شيفرتك.	
define("__FOO__", "something"); 
?>

ملاحظة: في هذا الدليل الحرف هو كل ما يقع ضمن النطاق a-z و A-Z والبايتات من 127 إلى 255 (0x7f-0xff).

كما هو الحال مع ذوات النطاق العام العالي (superglobals)، فإن الثوابت موجودة ضمن النطاق العام، ويمكن الوصول إليها من أي مكان في الشيفرة دون الحاجة إلى مراعاة النطاق الحالي. لمزيد من المعلومات حول النطاق راجع صفحة مجال المتغيرات في هذا الدليل.

الصيغة

يمكن تعريف الثابت باستخدام الدالة define()‎ أو باستخدام الكلمة المفتاحية const خارج الأصناف منذ الإصدار 5.3.0 من PHP. تتيح define()‎ إسناد الثوابت إلى مختلف أنواع القيم والتعبيرات، في حين أن هناك بعض القيود التي تحكم استخدام const وهو ما سنبينه في الفقرة التالية. لا يمكن بأيّ حال من الأحوال تغيير قيمة الثابت أو إلغاء القيمة المسندة إليه بعد إجراء عملية الإسناد.

كان استخدام const محدّدًا بالقيم الأولية (scalar values، أي القيم المنطقية والأعداد الصحيحة والأعداد العشرية والسلاسل النصية) في الإصدارات السابقة للإصدار 5.6 من PHP. في الإصدارات اللاحقة أصبح بالإمكان تعريف الثابت كتعبير عددي، وأصبح من الممكن أيضًا تعريف مصفوفات ثابتة. يمكن كذلك تعريف الثوابت كمصادر (resources) إلا أنّ ذلك ليس أمرًا محبّذًا فقد يتسبّب في ظهور نتائج غير متوقعة.

يمكن الحصول على قيمة الثابت بواسطة اسمه، وعلى العكس من المتغيرات فلا حاجة لأن يكون الاسم مسبوقًا بعلامة $. يمكن كذلك استخدام الدالة constant()‎ لقراءة قيمة الثابت إن كان المطلوب هو الحصول على اسم الثابت ديناميكيًا. وللحصول على قائمة بجميع الثوابت المعرّفة يمكن استخدام الدالة get_defined_constants()‎.

ملاحظة: تقع الثوابت والمتغيرات (العامة) في نطاقات أسماء (namespace) مختلفة، وهذا يعني أنّ TRUE و ‎$TRUE (على سبيل المثال) مختلفان عن بعضهما بعضًا.

إن لم تُسنَد أيّ قيمة للثابت ستفترض PHP أن المقصود هو اسم الثابت نفسه، كما لو كان الاستدعاء لسلسلة نصية (CONSTANT مقابل "CONSTANT"). سينبثق خطأ من المستوى E_NOTICE عند حدوث هذا الأمر. راجع صفحة نوع البيانات array لمعرفة السبب الذي يجعل التعبير ‎$foo[bar]‎ خطأ (إلا إذا استخدمنا define()‎ لتعريف bar كثابت). ما سبق لا ينطبق على الثوابت المؤهلة qualified (كليًا) حيث سينبثق خطأ قاتل (fatal error) في حال عدم تعريف هذا النوع من الثوابت. إن كنت ترغب في معرفة ما إذا كان الثابت معرّفًا أو لا، يمكنك استخدام الدالة defined()‎.

إليك الفوارق التي تميز الثوابت عن المتغيرات:

  • الثوابت غير مسبوقة بعلامة $.
  • قبل الإصدار 5.3 يمكن تعريف الثوابت باستخدام الدالة define()‎ فقط، وليس من خلال الإسناد البسيط.
  • يمكن تعريف الثوابت والوصول إليها في أي مكان دون أخذ النطاق الحالي بالحسبان.
  • لا يمكن إعادة أو إلغاء تعريف الثوابت بعد تعريفها.
  • يمكن استخدام الثوابت مع القيم الأوليّة فقط. في الإصدار 5.6 وما بعده من PHP أصبح بالإمكان تعريف مصفوفات ثابتة باستخدام الكلمة المفتاحية const. وفي الإصدار 7 من PHP أصبح بالإمكان استخدام الدالة define()‎ لتعريف المصفوفات الثابتة. يمكن استخدام المصفوفات الثابتة في التعبيرات العددية الثابتة (مثل: const FOO=array(1,2,3)[0];‎) ولكن يجب أن تكون النتيجة النهائية قيمةً ذات نوع مقبول في PHP.

المثال 1: تعريف الثوابت

<?php
define("CONSTANT", "Hello world.");
// "Hello world."
echo CONSTANT;
echo Constant;
// "Constant"
// وسينبثق تنبيه.
?>

المثال 2: تعريف الثوابت باستخدام الكلمة المفتاحية const

<?php
// تعمل منذ الإصدار 5.3.0 من اللغة
const CONSTANT = 'Hello World';


echo CONSTANT;


// تعمل منذ الإصدار 5.6.0 من اللغة
const ANOTHER_CONST = CONSTANT.'; Goodbye World';
echo ANOTHER_CONST;


const ANIMALS = array('dog', 'cat', 'bird');
echo ANIMALS[1];
// "cat"


// تعمل منذ الإصدار 7 من اللغة
define('ANIMALS', array(
    'dog',
    'cat',
    'bird'
));
echo ANIMALS[1];
// "cat"
?>

ملاحظة: تختلف الثوابت المعرّفة باستخدام الكلمة المفتاحية const عن تلك المعرّفة بواسطة الدالة define()‎ في أن التصريح عن الأولى يجب أن يكون في المجال الرئيسية (top-level scope) حصرًا لأن هذه الثوابت تُعرّف في وقت التصريف (compile-time)، وهذا يعني عدم إمكانية التصريح عنها داخل الدوال أو الحلقات أو العبارات الشرطية أو ضمن كتلة try/catch.

ملاحظة: تكون الثوابت المعرّفة باستخدام الكلمة المفتاحية const حساسة لحالة الأحرف دائمًا، في حين أن الثوابت المعرفة بواسطة الدالة define()‎ قد لا تكون حساسة لحالة الأحرف.

راجع كذلك ثوابت الأصناف.

الثوابت السحرية

توفّر PHP عددًا كبيرًا من الثوابت المعرّفة مسبقًا للشيفرات التي تشغلها، ولكن ينشأ العديد من هذه الثوابت بواسطة ملحقات متعددة، وتكون الثوابت متاحة عند توفّر هذه الملحقات إما بواسطة التحميل الديناميكي (dynamic loading) أو بسبب كونها مبنية مع اللغة (compiled in).

هناك تسعة ثوابت سحرية تتغير بالاعتماد على مكان استخدامها. فعلى سبيل المثال تعتمد قيمة الثابت __LINE__ على السطر المستخدم في الشيفرة. تحلل جميع هذه الثوابت السحرية في وقت التصريف (compile time) بخلاف الثوابت الاعتيادية التي تحلّل في وقت التشغيل (runtime). هذا النوع الخاص من الثوابت غير حساس لحالة الأحرف. فيما يلي قائمة بهذه الثوابت:

الاسم الوصف
__LINE__ رقم السطر الحالي في الملف.
__FILE__ المسار الكامل واسم الملف مع تحليل الوصلات الرمزية (symlinks). إن استخدم هذا الثابت في ملف مضمّن فإن النتيجة ستكون اسم الملف المضمّن.
__DIR__ المجلد الذي يحتوي على الملف. إن  استخدمه في ملفّ مضمّن تكون النتيجة اسم المجلّد الذي يضمّ الملف المضمّن. هذا الثابت مكافئ لاستخدام الدالة dirname(__FILE__)‎. لا يكون هذا المجلد مسبوقًا بخطوط مائلة slash إلا إذا كان المجلد الجذر (root directory).
__FUNCTION__ اسم الدالة.
__CLASS__ اسم الصنف. ويشمل اسم الصنف كذلك مجال الأسماء (namespace) الذي صُرّح عن الصنف فيه (مثل Foo\Bar). لاحظ أنه منذ الإصدار 5.4 من PHP فإن __CLASS__ تعمل في السمات (traits) أيضًا. عند استخدام هذا الثابت في توابع خاصة بالسمات، يعطي __CLASS__ اسم الصنف الذي استخدمت فيه هذه السمة.
__TRAIT__ اسم السمة. يشمل اسم السمة نطاق الاسم الذي صرّح عن السمة فيه. (مثال: Foo\Bar).
__METHOD__ اسم تابع الصنف.
__NAMESPACE__ اسم نطاق الأسماء الحالي.
ClassName::class الاسم الكامل المؤهّل للصنف (fully qualified class name). راجع أيضًا ‎::class

سجل التغييرات

الإصدار الوصف
5.5.0 إضافة الثابت السحري ‎::class
5.4.0 إضافة الثابت __TRAIT__
5.3.0 إضافة الثابتين __DIR__ و __NAMESPCE__
5.0.0 إضافة الثابت __METHOD__
5.0.0 قبل هذا الإصدار كانت قيم بعض الثوابت السحرية تكتب بالأحرف الصغيرة. أما الآن فجميعها حساس لحالة الأحرف (تحتوي على الأسماء كما أُفصح عنها).
4.3.0 إضافة الثابتين __FUNCTION__ و __CLASS__
4.0.2 يحتوي الثابت __FILE__ دائمًا على مسار مطلق مع تحليل الوصلات الرمزية، في حين أنه في الإصدارات الأقدم احتوى هذا الثابت على روابط نسبية في بعض الحالات.

مصادر