پرش به مطلب اصلی

شمارشگرها (Enums)

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

تعریف موارد

فاصله‌گذاری

اطمینان حاصل کنید که بین موارد فاصله‌ای وجود ندارد و همه آنها زیر یکدیگر تراز شده‌اند.

درست:

enum ProductAccessType: int
{
case Subscriber = 1;
case Private = 2;
case Organization = 3;
case Interview = 4;
}

نادرست:

enum ProductAccessType: int
{
case Subscriber = 1;

case Private = 2;

case Organization = 3;

case Interview = 4;
}

نام‌گذاری

برای موارد شمارشگر از PascalCase استفاده کنید. این کار آنها را از متغیرها و متدها به راحتی قابل تشخیص می‌کند.

درست:

enum ProductAccessType: int
{
case Subscriber = 1;
case Private = 2;
}

نادرست:

enum ProductAccessType: int
{
case subscriber = 1;
case private = 2;
}

متدهای کمکی

toPersian()

یک متد toPersian() برای شمارشگرهایی که نیاز به نمایش متن فارسی برای مقادیر خود دارند، پیاده‌سازی کنید. این برای محتوای مواجه با کاربر مفید است.

enum ProductAccessType: int
{
case Subscriber = 1;
case Private = 2;
case Organization = 3;
case Interview = 4;

public function toPersian(): string
{
return match($this) {
self::Subscriber => 'اشتراک',
self::Private => 'خصوصی',
self::Organization => 'سازمانی',
self::Interview => 'مصاحبه',
};
}
}

PersianList()

یک متد استاتیک PersianList() برای بازگرداندن آرایه‌ای از تمام موارد شمارشگر با ترجمه‌های فارسی آنها پیاده‌سازی کنید. این برای تولید لیست‌های کشویی یا سایر عناصر رابط کاربری مفید است.

enum ProductAccessType: int
{
case Subscriber = 1;
case Private = 2;
case Organization = 3;
case Interview = 4;

public function toPersian(): string
{
return match($this) {
self::Subscriber => 'اشتراک',
self::Private => 'خصوصی',
self::Organization => 'سازمانی',
self::Interview => 'مصاحبه',
};
}

public static function PersianList(): array
{
return [
self::Subscriber->value => self::Subscriber->toPersian(),
self::Private->value => self::Private->toPersian(),
self::Organization->value => self::Organization->toPersian(),
self::Interview->value => self::Interview->toPersian(),
];
}
}

چه زمانی از شمارشگرها استفاده کنیم

در سناریوهای زیر از شمارشگرها استفاده کنید:

  1. زمانی که مجموعه ثابتی از ثابت‌های مرتبط دارید
  2. برای مقادیر وضعیت، انواع، دسته‌ها یا هر طبقه‌بندی دیگر
  3. زمانی که به ایمنی نوع برای مجموعه خاصی از مقادیر نیاز دارید
  4. زمانی که مقادیر دارای رفتار یا ویژگی‌های مرتبط هستند

مزایای استفاده از شمارشگرها

  • ایمنی نوع: کامپایلر اطمینان می‌دهد که فقط مقادیر شمارشگر معتبر استفاده می‌شوند
  • کد خود-مستندساز: موارد شمارشگر به وضوح مقادیر ممکن را منتقل می‌کنند
  • تعریف متمرکز: تمام ثابت‌های مرتبط در یک مکان تعریف می‌شوند
  • پشتیبانی IDE: تکمیل خودکار برای موارد و متدهای شمارشگر

مثال‌ها

مثال 1: نقش‌های کاربر

enum UserRole: string
{
case Admin = 'admin';
case Editor = 'editor';
case Author = 'author';
case Subscriber = 'subscriber';

public function toPersian(): string
{
return match($this) {
self::Admin => 'مدیر',
self::Editor => 'ویرایشگر',
self::Author => 'نویسنده',
self::Subscriber => 'مشترک',
};
}

public function canEditPosts(): bool
{
return match($this) {
self::Admin, self::Editor, self::Author => true,
self::Subscriber => false,
};
}
}

مثال 2: وضعیت سفارش

enum OrderStatus: int
{
case Pending = 1;
case Processing = 2;
case Shipped = 3;
case Delivered = 4;
case Cancelled = 5;

public function toPersian(): string
{
return match($this) {
self::Pending => 'در انتظار',
self::Processing => 'در حال پردازش',
self::Shipped => 'ارسال شده',
self::Delivered => 'تحویل داده شده',
self::Cancelled => 'لغو شده',
};
}

public function isActive(): bool
{
return match($this) {
self::Pending, self::Processing, self::Shipped => true,
self::Delivered, self::Cancelled => false,
};
}
}

شمارشگرها چگونه در سیستم کشف و شناسایی می‌شوند؟

برای ایجاد APIهای شمارشگر پویا و جدا از ارجاعات کلاس کدگذاری شده، از یک مکانیسم کشف و نگاشت خودکار استفاده می‌کنیم:

  1. کشف شمارشگر از طریق Reflection

    • یک دستور ویژه (fetch enums) کل کد منبع پروژه را با استفاده از PHP reflection اسکن می‌کند.
    • تمام کلاس‌هایی که شمارشگر هستند را پیدا می‌کند و یک نگاشت از نام‌های شمارشگر به نام‌های کلاس کاملاً واجد شرایط آنها ایجاد می‌کند.
  2. کش نقشه شمارشگر

    • نگاشت کشف شده به عنوان یک آرایه کلید-مقدار در /var/www/planet/lsp/bootstrap/cache/enums_map.php ذخیره می‌شود.
    • مثال ورودی:
      enums_map.php
      return [
      'StatusType' => App\\Enums\\StatusType::class,
      'UserRole' => App\\Enums\\UserRole::class,
      // ...
      ];
  3. استفاده در زمان اجرا در EnumController

    • هنگامی که یک درخواست API انجام می‌شود (مثلاً admin.enums.show?enum=StatusTypeEnumController نام شمارشگر را در این نقشه کش شده جستجو می‌کند.
    • سپس به صورت پویا کلاس Enum صحیح را با استفاده از نام کاملاً واجد شرایط حل و نمونه‌سازی می‌کند.
    • این به سیستم اجازه می‌دهد تا هر شمارشگر ثبت شده را بدون نیاز به به‌روزرسانی منطق کنترلر برای هر شمارشگر جدید مدیریت کند.
نکته

این مکانیسم اطمینان می‌دهد که APIهای شمارشگر همیشه با پایگاه کد به‌روز هستند، و شمارشگرهای جدید پس از اجرای دستور fetch به طور خودکار در دسترس قرار می‌گیرند.

نقاط پایانی API شمارشگر و خودکارسازی

اطلاع

APIهای شمارشگر مدیر

برای تسهیل کار با شمارشگرها در پنل مدیریت، سه نقطه پایانی API اختصاصی داریم، همه به عنوان مسیرهای GET تعریف شده‌اند و داده‌ها را از طریق EnumTransformer استاندارد شده بازمی‌گردانند:

  • admin.enums.index

    • هدف: بازیابی داده‌ها برای چندین شمارشگر به طور همزمان.
    • پارامتر: enum (رشته) — لیست نام‌های شمارشگر جدا شده با کاما.
    • پاسخ: مجموعه‌ای از اشیاء داده شمارشگر.
  • admin.enums.show

    • هدف: بازیابی داده‌ها برای یک شمارشگر واحد.
    • پارامتر: نام شمارشگر (رشته).
    • پاسخ: شیء داده شمارشگر.
  • admin.enums.keyValList

    • هدف: بازیابی جفت‌های کلید-مقدار برای یک شمارشگر واحد، مناسب برای پر کردن ورودی‌های انتخاب.
    • پارامتر: نام شمارشگر (رشته).
    • پاسخ: لیست کلید-مقدار گزینه‌های شمارشگر.

تمام این مسیرها بخشی از API مدیر هستند و داده‌ها را با استفاده از استاندارد EnumTransformer برمی‌گردانند.

مثال استفاده

مثال: دریافت چندین شمارشگر
GET /api/admin/enums/index?enum=StatusType,UserRole
نمونه پاسخ
[
{
"name": "StatusType",
"values": [ ... ]
},
{
"name": "UserRole",
"values": [ ... ]
}
]