آشنایی با مفهوم Constant در زبان PHP


Constant در لغت به معنای «ثابت» است و همچون متغیر، فضایی در حافظه است که مسئول ذخیره‌سازی چیزی است با این تفاوت که -همان‌طور که از نامش مشخص است- برخلاف متغیرها که مقادیر آنها قابل‌تغییر است، مقدار اولیهٔ کانستنت‌ها را نمی‌توان تغییر داد و به همین دلیل گفته می‌شود که کانستنت‌ها اصطلاحاً Immutable (تغییرناپذیر) هستند.

نکته
در میان دولوپرهای زبان PHP رایج است که نامگذاری کانستنت‌ها را تماماً با حروف بزرگ انجام داده و برای مجزاسازی بخش‌های مختلف نام از Underscore یا همان علامت _ استفاده می‌کنند. گرچه از حروف کوچک هم می‌توان استفاده کرد، اما برای آنکه به راحتی بتوان در طول زمان کانستنت‌ها را تشخیص داد، بهتر آن است که از حروف بزرگ در کل وب اپلیکیشن استفاده کرد.

شیوهٔ نام‌گذاری Constant در زبان PHP
روش نام‌گذاری کانستنت‌ها در این زبان دقیقاً مشابه نامگذاری متغیرها است بدین صورت که:
- نام کانستنت‌ می‌تواند ترکیبی از حروف، اعداد و _ باشد (مثلاً USER_AGENT)
- اولین حرف در نام کانستنت‌ باید یک حرف انگلیسی یا علامت _ باشد (مثلاً 1USER_AGENT مورد قبول نیست؛ البته پس از اولین حرف می‌توان از اعداد استفاده کرد مثلاً USER_1_AGENT).
- نام کانستنت‌‌ها در زبان PHP اصطلاحاً Case-sensitive است؛ به عبارت دیگر، مفسر این زبان به حروف بزرگ و کوچک در ارتباط با کانستنت‌‌ها حساس است (مثلاً از دید مفسر این زبان USER_AGENT با user_agent دو کانستنت مختلف محسوب می‌شوند).
- برای نام‌گذاری کانستنت‌ها از علامت - نمی‌توان استفاده کرد.

هشدار
به خاطر داشته باشید که برای نام‌گذاری کانستنت‌ها، هرگز از علامت $ استفاده نکنید.

چند نمونه از نام‌های اشتباه برای کانستنت‌ها در PHP عبارتند از:

2CONSTANT_NAME // Using a number at the beginning
CONSTANT-NAME // Using dash
$CONSTANT_NAME // Using a $ sign at the beginning

گرچه می‌توان کانستنتی مثلاً تحت عنوان __NAME__ ایجاد کرد، اما از آنجا که در هستهٔ زبان PHP یکسری کانستنت‌ها داریم که اصطلاحاً Magic Constant نامیده می‌شوند که شیوهٔ نام‌گذاری آنها بدین شکل است (یعنی استفاده از دو علامت __ در ابتدا و دو علامت __ در انتهای نام کانستنت)، توصیه می‌شود که از این شیوه استفاده نشود که اگر در آینده دولوپرهای PHP تصمیم گرفتند مجیک کانستنتی هم‌نام با کانستنت شما در این زبان بگنجانند، با مشکل برخورد نکنید.

آشنایی با روش‌های تعریف  Constant در زبان PHP
به منظور ساخت یک کانستنت در زبان PHP دو راه‌کار مختلف پیش روی ما است اما این در حالی است که این دو روش تفاوت‌هایی هم با یکدیگر دارند.

- استفاده از فانکشن ()define: راه‌کار اول استفاده از فانکشنی است تحت عنوان ()define. به طور مثال داریم:

define("SITE_NAME", "SokanAcademy");
echo SITE_NAME;

به عنوان خروجی داریم:

SokanAcademy

حال اسکریپت فوق را به صورت زیر بازنویسی می‌کنیم:

define("SITE_NAME", "SokanAcademy");
echo site_name;

به عنوان خروجی داریم:

Notice: Use of undefined constant site_name - assumed 'site_name' in /var/www/sokanacademy-php-course/02/02-variable/index.php on line 3

می‌بینیم که مفسر پی‌اچ‌پی به ما هشدار می‌دهد که چنین کانستنتی -site_name- قبلاً تعریف نشده است. پیش از این گفتیم که کانستنت‌ها همچون متغیرها، اصطلاحاً Case-sensitve هستند. حال اگر بخواهیم آنها را اصطلاحاً Case-insensitive کنیم به صورت زیر عمل می‌کنیم:

define("SITE_NAME", "SokanAcademy", true);
echo site_name;

به عنوان خروجی داریم:

SokanAcademy

در واقع، کاری که پارامتر سوم انجام می‌دهد (که به صورت پیش‌فرض معادل با false است) این است که قابلیت Case-insensitive را برای کانستنت ما فعال می‌سازد. به عبارت دیگر، از این پس می‌توانیم برای دستیابی به مقدار SokanAcademy از نام‌هایی همچون SITE_NAME ،site_name ،Site_Name و یا sITe_NamE استفاده کنیم اما به خاطر داشته باشید که علامت _ همواره می‌بایست سر جایش باقی بماند که در غیر این صورت با ارور مواجه خواهیم شد.

همان‌طور که در مثال فوق مشاهده می‌شود، از یک استرینگ به عنوان Value (مقدار) کانستنت خود استفاده کرده‌ایم. در زبان PHP از دیتاتایپ‌های مختلفی می‌توان به عنوان مقدار کانستنت‌ها استفاده کرد که عبارتند از integer ،float ،string ،boolean ،null و array (لازم به ذکر است که آرایه‌ها از نسخهٔ ۷ به بعد اضافه شده‌اند).

هشدار
اگرچه از دیتاتایپ Resource که پیش از این با مفهومش در زبان PHP آشنا شدید می‌توان به عنوان مقدار کانستنت‌ها استفاده کرد، اما این کار اصلاً توصیه نمی‌شود چرا که در برخی مواقع نتایج غیرمنتظره‌ای مشاهده خواهد شد.

گفتیم که در نسخهٔ ۷ زبان PHP می‌توان از آرایه‌ها به عنوان مقدار کانستنت استفاده کرد. برای روشن‌تر شدن این مطلب، به اسکریپت زیر توجه کنید:

define('ANIMALS', array('dog','cat','bird'));
echo ANIMALS;

به عنوان خروجی اسکریپت فوق داریم:

Notice: Array to string conversion in /var/www/sokanacademy-php-course/02/02-variable/index.php on line 3

می‌بینیم که ارور دریافت کردیم. علت این مسئله آن است که دستور echo را نمی‌توان برای چاپ کردن یک آرایه مورد استفاده قرار داد. برای رفع این مشکل، یا می‌توان از فانکشن ()print_r و یا ()var_dump استفاده کرد:

define('ANIMALS', array('dog','cat','bird'));
print_r(ANIMALS); // or var_dump(ANIMALS)

حال به عنوان خروجی داریم:

Array
(
    [0] => dog
    [1] => cat
    [2] => bird
)

همچنین در نظر داشته باشید که برای تعریف کردن آرایه‌ها در زبان PHP از روش دیگری نیز می‌توان استفاده کرد:

define('ANIMALS', ['dog','cat','bird']);
var_dump(ANIMALS);

همان‌طور که ملاحظه می‌شود، به جای دستور ()array از علائم [ ] استفاده کرده‌ایم که به نظر خلاصه‌تر می‌آید.

- استفاده از کلیدواژهٔ const: با استفاده از const هم به سادگی می‌توان دست به ایجاد یک کانستنت زد. به عنوان مثال داریم:

const SITE_NAME = "SokanAcademy";
echo SITE_NAME;

به عنوان خروجی هم داریم:

SokanAcademy

می‌بینیم که عملکرد کاملاً مشابه است. اساسی‌ترین تفاوتی‌هایی که مابین کلیدواژهٔ const و فانکشن ()define برای ایجاد کانسنت‌ها در زبان PHP وجود دارد این است که const همواره Case-sensitive است. به عبارت دیگر، برخلاف فانکشن ()define که دیدیم پارامتر سوم‌اش این امکان را در اختیار ما می‌گذارد تا کانستنت خود را Case-insensitive کنیم.

همچنین گفته می‌شود که const در حین Compile-time ساخته می‌شود اما ()define در Run-time و همین منجر می‌گردد که کانستنت‌های ساخته شده با const کمی سریع‌تر باشند. باتوجه به اینکه const در زمان کامپایل ساخته می‌شود، مسلماً از آن همراه با دستورات شرطی نمی‌توان استفاده کرد:

if (!defined('SITE_NAME')) {
      const SITE_NAME = "SokanAcademy";
}
echo SITE_NAME;

به عنوان خروجی داریم:

Parse error: syntax error, unexpected 'const' (T_CONST) in /var/www/sokanacademy-php-course/02/02-variable/index.php on line 

حال کد فوق را به صورت زیر ریفکتور می‌کنیم:

if (!defined('SITE_NAME')) {
    define('SITE_NAME', 'SokanAcademy');
}
echo SITE_NAME;

به عنوان خروجی داریم:

SokanAcademy

در تفسیر رفتار PHP در دو مورد فوق بایستی بگوییم که در اسکریپت اول، چون const در حین فرایند کامپایل ایجاد می‌گردد اما این در حالی است که دستور شرطی if در زمان Run-time بررسی می‌شود و مسلماً دیگر برای ساخت const دیر شده است (زیرا Compile پیش از Run صورت می‌گیرد)، با ارور مواجه می‌شویم اما در اسکریپت دوم به خاطر اینکه فانکشن ()define دقیقاً همان زمانی که دستور if بررسی می‌شود می‌تواند ساخته شود، بدون هیچ مشکلی برنامه به پیش خواهد رفت (البته تفاوت‌های const و ()define مراتب بیش از آن چیزی است که در بالا گفته شد که مناسب دولوپرهای حرفه‌ای PHP است).

نکته‌‌ای که در ارتباط با کانستنت‌ها می‌بایست مد نظر قرار داد این است که برخلاف متغیرها که محدود به Scope (اسکوپ یا حوزه) خاصی هستند، کانستنت‌ها اصطلاحاً Global (سراسری) بوده و فرقی نمی‌کند که کجا آنها را تعریف کنید، چرا که در تمامی اسکریپت شما قابل دستیابی می‌باشند.

نکتهٔ دیگری که در مورد کانستنت‌ها وجود دارد این است که از یک متغیر هرگز نمی‌توان به عنوان مقدار یک کانستنت استفاده کرد:

$siteName = 'SokanAcademy';
const SITE_NAME = $siteName;
echo SITE_NAME;

به عنوان خروجی اسکریپت فوق داریم:

Fatal error: Constant expression contains invalid operations in /var/www/sokanacademy-php-course/index.php on line 3

می‌بینیم که با چنین کاری اروری از جنس Fatal (وَخیم) دریافت می‌کنیم.

آشنایی با فانکشن‌های ()defined و ()get_defined_constants
دو فانکشن در زبان PHP وجود دارند که مرتبط با کانستنت‌ها هستند که آگاهی از عملکرد آنها خالی از لطف نیست (البته فانکشن‌های دیگری هم وجود دارند که خیلی کاربردی نیستند). پیش از این با فانکشن ()defined همراه با دستورات شرطی آشنا شدیم که این وظیفه را دارا است تا مشخص سازد که آیا کانستنتی که به عنوان پارامتر ورودی‌اش پاس داده‌ایم وجود دارد یا خیر. به عنوان مثال داریم:

if (defined('TEST')) {
    echo TEST;
}

در تفسیر دستور شرطی فوق بایستی بگوییم که چک کرده‌ایم ببینیم که آیا کانستنتی با نام TEST وجود دارد یا خیر؛ اگر وجود داشت که با دستور echo مقدار آن را چاپ خواهیم کرد و در غیر این صورت، هیچ اتفاقی رخ نخواهد داد.

فانکشن ()get_defined_constants هم همان‌طور که از نام‌اش پیدا است، این وظیفه را دارا است تا کلیهٔ کانستنت‌هایی که تاکنون در اسکریپت تعریف شده‌اند را در معرض دیدمان قرار دهد. اگر این فانکشن را به صورت (get_defined_constants(true مورد استفاده قرار دهیم، یعنی true را به عنوان پارامتر ورودی‌اش در نظر بگیریم، کلیهٔ‌ کانستنت‌ها به صورت دسته‌بندی شده در معرض دیدمان قرار خواهند گرفت.

آشنایی با کانستنت‌های به اصطلاح Predefined
در زبان PHP یکسری کانسنت‌های Predefined (از پیش تعریف شده) وجود دارند که اطلاعات خوبی در اختیار دولوپر قرار می‌دهند. به عنوان مثال،‌ برای آگاهی یافتن از نسخهٔ PHP نصب شده روی سیستم، می‌توان از کانستنت زیر استفاده کرد:

echo PHP_VERSION;

به عنوان خروجی داریم:

7.0.22-0ubuntu0.17.04.1

می‌بینیم که علاوه بر نسخهٔ PHP نصب شده روی سیستم‌عامل، نسخهٔ خود سیستم‌عامل را هم در اختیار ما قرار می‌دهد. به منظور آشنایی با کلیهٔ کانسنت‌های از پیش تعریف شده در زبان PHP می‌توانید به لینک Predefined Constants در سایت رسمی PHP مراجعه نمایید.

آشنایی با کانستنت‌های به اصطلاح Magic (جادویی) در PHP
در زبان PHP تعدادی کانستنت‌ از پیش تعریف شده وجود دارند که اصطلاحاً Magic (جادویی) نامیده می‌شوند که عبارتند از:

کاربرد نام کانستنت جادویی
خطی از اسکریپت که در آن قرار داریم را نشان می‌دهد. __LINE__
مسیر کامل و نام فایلی که در حال اجرا است را نشان می‌دهد. __FILE__
دایرکتوری که فایل مد نظر داخل آن قرار دارد را نشان می‌دهد. __DIR__
نام فانکشنی که در حال اجرا است را نشان می‌دهد. __FUNCTION__
نام کلاسی که داخل آن قرار داریم را نشان می‌دهد. __CLASS__
نام تِریتی که داخل آن قرار داریم را نشان می‌دهد. __TRAIT__
نام متدی که داخل آن قرار داریم را نشان می‌دهد. __METHOD__
نِیم‌اسپیسی که داخل آن قرار داریم را نشان می‌دهد. __NAMESPACE__

به منظور درک ماهیت کانستنت‌های جادویی، چند مثال می‌زنیم:

<?php
echo __LINE__;

به عنوان خروجی داریم:

2

و یا:

<?php
echo __FILE__;

به عنوان خروجی داریم:

/var/www/sokanacademy-php-course/02/02-variable/index.php

به خاطر داشته باشیم که از کانستنت‌های به اصطلاح Magic (جادویی) می‌توان به عنوان مقدار یک کانستنت نیز استفاده کرد:

const DIRECTORY = __DIR__;
echo DIRECTORY;

به عنوان خروجی اسکریپت فوق داریم:

/var/www/sokanacademy-php-course/02
به خاطر داشته باشید
یادآوری این نکته ضروری است که بسته به جایی که از کانستنت‌های جادویی استفاده می‌کنیم، مقادیر آنها می‌توانند متفاوت باشند.
لیست نظرات
کاربر میهمان
دیدگاه شما چیست؟
کاربر میهمان
محسن
محسن
از جمله تفاوت های const و فانکشن ()define همونطور که گفته شد این هست که const در حین Compile-time ساخته می‌شود اما ()define در Run-time
به تعریف ساده تر با استفاده از تابع define در واقع هیچ متغیری به معنای واقعی ساخته نمی شه و فقط یک جایگذاری ساده قبل از کامپایل شدن کدها انجام می شه در صورتی که هنگام استفاده از کلمه کلیدی const به صورت واقعی یک متغیر تعریف و ساخته می شه
Insight
Insight
اگه در کدنویسی از مقادیر جادویی (Magic Values) به دفعات زیادی استفاده بشه، اصطلاحا به شیوه Hard Coding گفته میشه. استفاده از این روش به شدت نهی میشه چون علاوه بر کاهش خوانایی سورس‌کد، ممکنه با داده‌های واقعی کاربران یا اطلاعات دیگه ناسازگار باشه.
در مقابل روش دیگری تحت عنوان Soft Coding وجود داره و مفهومی متضاد قبلی داره و به روشی اطلاق میشه که به مقادیری جدای از سورس‌کد وابستگی زیادی وجود داشته باشه. استفاده از این روش هم توصیه نمیشه.