آموزش نحوهٔ استفاده از Enumeration در زبان PHP


در علوم کامپیوتر و ریاضیات، Enumeration یا به اختصار Enum به لیستی از چندین آیتم مرتبط با یکدیگر اطلاق می‌گردد که در زبان‌های برنامه‌نویسی مطرحی همچون جاوا، این مفهوم به صورت پیش‌فرض در هستهٔ این زبان پیاده‌سازی شده است. به طور کلی، چنین دیتا تایپی در زبان برنامه‌نویسی پی‌اچ‌پی به صورت نِیتو وجود نداشت اما پس از عرضهٔ SPL، کلاسی تحت عنوان SplEnum به لایبرری استاندارد این زبان افزوده شد تا با استفاده از آن بتوان از چنین دیتا تایپی در توسعهٔ نرم‌افزار استفاده نمود؛ البته لازم به یادآوری است که این کلاس به صورت پیش‌فرض با نصب پی‌اچ‌پی روی سیستم نصب نخواهد شد و به صورت مجزا می‌باید آن را نصب نمود (جهت آشنایی بیشتر با مفهوم SPL، می‌توانید به آموزش آشنایی با PHP Standard Library مراجعه نمایید.)

پیش از پرداختن به این کلاس، لازم به یادآوری است که گاهی می‌توان از Constant به جای Enum استفاده نمود که چنین کاری مشکلات خاص خود را خواهد داشت که برای درک بهتر این موضوع، در ادامه ابتدا در فضای لوکال‌هاست پروژه‌ای با نامی دلخواه همچون enum ساخته سپس فایلی به نام composer.json حاوی ساختار زیر در مسیر روت این پروژه ایجاد می‌کنیم:

{}

همان‌طور که ملاحظه می‌شود، یک آبجکت خالی ایجاد کرده‌ایم؛ سپس کامند زیر را اجرا می‌کنیم:

/var/www/enum$ composer dump-autoload -o

در صورت موفقیت‌آمیز بودن کامند فوق، خواهیم دید که پوشه‌ای جدید تحت عنوان vendor در مسیر روت پروژه ساخته می‌شود که حاوی فایلی تحت عنوان autoload.php است که با استفاده از آن به سادگی قادر خواهیم بود تا به صورت خودکار، کلاس‌های مورد استفاده در جای‌جای پروژه را ایمپورت نماییم (جهت آشنایی بیشتر با پروسهٔ اُتولودینگ در زبان برنامه‌نویسی پی‌اچ‌‌پی، می‌توانید به آموزش آشنایی با مفاهیم Class و Object در متودولوژی OOP مراجعه نمایید.) حال در ادامه پوشهٔ دیگری تحت عنوان classes در مسیر روت این پروژه ایجاد می‌کنیم که وظیفهٔ نگهداری کلاس‌های مختلف را دارا است اما پیش از ساخت هر گونه کلاسی، مجدد به فایل composer.json بازگشته و آن را به صورت زیر تکمیل می‌کنیم:

{
    "autoload": {
        "psr-4": {
            "EnumSample\\": "classes"
        }
    }
}

در واقع، بر اساس استاندارد PSR-4 نِیم‌اِسپیسی با نامی دلخواه همچون EnumSample ساخته که به پوشهٔ classes اشاره دارد (در همین راستا، توصیه می‌شود برای کسب اطلاعات بیشتر در این خصوص به آموزش آشنایی با مفهوم PHP Standard Recommendation مراجعه نمایید.) در ادامه، داخل پوشهٔ classes فایلی به نام User.php حاوی محتویات زیر می‌سازیم:

<?php
namespace EnumSample;

class User
{
     const GENDER_MALE = 0;
     const GENDER_FEMALE = 1;
     const STATUS_INACTIVE = 0;
     const STATUS_ACTIVE = 1;
}

پس از تعریف نِیم‌اِسپیس، در بلوک کد فوق کلاسی ساخته‌ایم تحت عنوان User که در آن چهار کانستنت مختلف ایجاد کرده‌ایم که در دو گروه اِلِمان مختلف تقسیم‌بندی شده‌اند که عبارتند از *_GENDER و *_STATUS و هر کدام از آن‌ها حاوی یک سری تنظیمات برای به ترتیب «جنسیت» و «وضعیت» آبجکتی از جنس یوزر می‌باشند. به نوعی می‌توان هر کدام از گروه‌های فوق را به عنوان یک Enum در نظر گرفت و همان‌طور که پیش از این اشاره کردیم، این اصطلاح به مجموعه‌از از اِلِمان‌های مختلف اما مرتبط با هم اشاره دارد. حال در ادامه فایل دیگری می‌سازیم به نام UserFactory.php و کدهای زیر را داخل آن می‌نویسیم:

<?php
namespace EnumSample;

class UserFactory
{
    public function create(string $email, int $gender, int $status)
    {
        return "user email is: " . $email . "\nand gender is: " . $gender . "\nand status is: " . $status . "\n";
    }
}

کلاس UserFactory وظیفهٔ ساخت یک کاربر جدید را بر عهده دارد و برای همین منظور هم داخل آن متدی تحت عنوان ()create نوشته‌ایم که سه پارامتر ورودی می‌گیرد و داخل این متد صرفاً مقادیر پارامترهای ورودی را ریترن کرده‌ایم. حال خارج از پوشهٔ classes و در مسیر روت پروژه، فایل دیگری می‌سازیم به نام index.php و داخل آن آبجکت جدیدی از روی این کلاس می‌سازیم:

<?php
require_once "vendor/autoload.php";

$newUser = new EnumSample\UserFactory();
echo $newUser->create('hi@example.com', EnumSample\User::GENDER_MALE, EnumSample\User::STATUS_INACTIVE);

همان‌طور که ملاحظه می‌شود، ابتدا به ساکن فایل‌ autoload.php را با استفاده از دستور require_once ایمپورت کرده‌ایم سپس از روی کلاس UserFactory آبجکتی به نام newUser$ ساخته و در خط آخر هم با فراخوانی متد ()create و پاس دادن یک سری آرگومان، این متد را تکمیل کرده‌ایم و در صورتی که این فایل را اجرا کنیم، در خروجی خواهیم دید:

PHP Fatal error:  Uncaught Error: Class 'EnumSample\UserFactory' not found in /var/www/enum/index.php:4

متن ارور حاکی از آن است که کلاسی تحت عنوان UserFactory با نِیم‌اِسپیس EnumSample شناخته نشده است که برای رفع این مشکل، کامند زیر را اجرا می‌کنیم:

$ composer dump-autoload -o

کاری که این دستور انجام می‌دهد آن است که کلاس‌های جدید که داخل پروژهٔ خود ایجاد کرده‌ایم را به رسمیت خواهد شناخت و اگر اکنون مجدد این فایل را اجرا کنیم، به عنوان خروجی خواهیم داشت:

user email is: hi@example.com
and gender is: 0
and status is: 0

در ارتباط با آرگومان‌های دوم و سوم این متد باید گفت که از کانستنت‌های موجود داخل کلاس User استفاده نموده‌ایم و در نگاه اول این کد به درستی کار می‌کند اما مشکل اینجا است که با توجه به در نظر گرفتن مقدار صفر برای کانستنت‌های GENDER_MALE و STATUS_INACTIVE، حتی اگر توسعه‌دهنده سهواً جای این دو آرگومان را اشتباه در نظر گیرد، کد به صورت کاملاً تصادفی باز هم درست کار خواهد کرد به طوری که مثلاً داریم:

echo $newUser->create('hi@example.com', EnumSample\User::STATUS_INACTIVE, EnumSample\User::GENDER_MALE);

همچنین با توجه به این که از قابلیت Type Hinting زبان برنامه‌نویسی پی‌اچ‌پی استفاده ننموده‌ایم، متد فوق را به صورت زیر نیز می‌توان بدون هیچ گونه مشکلی کال نمود:

echo $newUser->create('hi@example.com', 2, 3);

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

user email is: hi@example.com
and gender is: 2
and status is: 3

برای رفع این معضل، می‌توان با استفاده از کلاس SplEnum کدهای اصولی‌تری اما آنچه در ادامه قصد داریم مورد بررسی قرار دهیم، یک لایبرری اپن‌سورس است تحت عنوان PHP Enum می‌باشد که با الهام از کلاس فوق توسعه یافته است.

این بخش از محتوا مخصوص کاربرانی است که ثبت‌نام کرده‌اند.
جهت مشاهدهٔ این بخش از محتوا لاگین نمایید.

جمع‌بندی
اساساً می‌توان گفت که Enum در فرآیند توسعهٔ نرم‌افزار این امکان را در اختیارمان می‌گذارد تا بتوانیم دیتا تایپی خاص تعریف نموده و یک سری اِلِمان مرتبط با یکدیگر را در آن‌ها ذخیره ساخت و این در حالی است که به‌کارگیری لایبرری PHP Enum این تضمین را می‌دهد که بتوانیم با استفاده از قابلیت Type Hinting زبان برنامه‌نویسی پی‌اچ‌پی، متدها را موظف به دریافت دقیقاً همان دیتا تایپی سازیم که مد نظر داریم.