با انتشار PHP 8.1، این زبان پشتیبانی بومی برای enums به دست آورد. Enums روشی مطمئن، قابل خواندن و کارآمد برای کپسوله کردن مجموعه کوچکی از مقادیر ممکن که یک فیلد می تواند در Model داده شما بگیرد، هستند. در صورت نیاز به افزودن به لیست در آینده، استفاده از کلاسها به جای فهرستهای پایگاه داده، انعطافپذیری بیشتری را فراهم میکند.
به عنوان مثال، شما یک مدل داده های کاربر دارید و آن کاربر ممکن است لیست خاصی از role ها را داشته باشد که می توانید از بین آنها انتخاب کنید.
namespace App\Enums;
enum UserRole: string
{
case Admin = 'admin';
case TeamAdmin = 'team_admin';
case Support = 'support';
case Basic = 'basic';
}
در مدل داده شما، لاراول همچنین از enums پشتیبانی میکند که اگر آن را در آرایه کستها تعریف کنید.
/**
* The attributes that should be cast.
*
* @var array<string,string|class-string>
*/
protected $casts = [
'role' => UserRole::class,
];
اگر بخواهیم نقشی را در مدل کاربر خود که در enum تعریف نشده است ذخیره کنیم، با افزودن گزینه enum casting، یک استثنا ایجاد میشود.
یک استفاده بسیار عملی از enums ایجاد مقادیر برای یک dropdown در HTML شما است.
<select name=”roles”>
@foreach(UserRole::cases() as $role)
<option value="{{ $role->value }}">{{ $role->name }}</option>
@endforeach
</select>
در ظاهر، هیچ مشکلی با مثال بالا به نظر نمی رسد داشته باشد تا زمانی که به نام قابل مشاهده هر گزینه در منو نگاه کنید. Admin و TeamAdmin نامهای متغیر خوبی هستند، اما Administrator و Team Administrator بهتر است در UI ارائه شوند، بنابراین کاملاً واضح است که چه role برای شخصی که role های کاربر را مدیریت میکند، دارد.
در حالی که enum ها برای جفت های ساده نام یا مقدار عالی هستند، در مواردی مانند این که نیاز به افزودن یک ویژگی سوم دارید، باید خلاق باشید.
ویژگی های PHP را وارد کنید. این روش که از مفهوم حاشیه نویسی در زبان های دیگر وام گرفته شده است، راهی برای مرتبط کردن ابرداده ها به ویژگی ها، روش ها و کلاس ها است که دقیقاً شبیه آنچه ما نیاز داریم به نظر می رسد.
ابتدا باید یک ویژگی Description بسازیم.
namespace App\Enums\Attributes;
use Attribute;
#[Attribute]
class Description
{
public function __construct(
public string $description,
) {
}
}
ما اکنون یک ویژگی Description داریم که میتوانیم از آن در enum استفاده کنیم تا بتوانیم نام نقشهای کاربرپسند مورد نظر خود را تعریف کنیم.
namespace App\Enums;
enum UserRole: string
{
#[Description('Administrator')]
case Admin = 'admin';
#[Description('Team Administrator')]
case TeamAdmin = 'team_admin';
case Support = 'support';
case basic = 'basic';
}
اکنون باید این ویژگی ها را بازیابی کنیم، که فقط از طریق انعکاس انجام می شود. از آنجایی که ممکن است بخواهیم از این ویژگی در فهرستهای دیگر استفاده کنیم، میخواهیم یک ویژگی برای آسانتر کردن این کار ایجاد کنیم.
namespace App\Enums\Concerns;
use Illuminate\Support\Str;
use ReflectionClassConstant;
use App\Enums\Attributes\Description;
trait GetsAttributes
{
/**
* @param self $enum
*/
private static function getDescription(self $enum): string
{
$ref = new ReflectionClassConstant(self::class, $enum->name);
$classAttributes = $ref->getAttributes(Description::class);
if (count($classAttributes) === 0) {
return Str::headline($enum->value);
}
return $classAttributes[0]->newInstance()->description;
}
}
اگر این روش را تجزیه کنیم، 2 خط اول از انعکاس برای بدست آوردن ویژگی های enum استفاده می کنند. از آنجایی که ممکن است هر enum ویژگی Description نداشته باشد، ما یک بازگشت به عقب برای تبدیل مقدار (یا نام) آن enum به عنوان توضیحات خود تنظیم می کنیم.
در نهایت، مقدار توضیحات را از صفات enum می گیریم. ما میتوانیم روش دیگری را به صفت خود اضافه کنیم تا بتوانیم این کار را انجام دهیم.
/**
* @return array<string,string>
*/
public static function asSelectArray(): array
{
/** @var array<string,string> $values */
$values = collect(self::cases())
->map(function ($enum) {
return [
'name' => self::getDescription($enum),
'value' => $enum->value,
];
})->toArray();
return $values;
}
اکنون، در HTML خود، میتوانیم به سادگی روشی را که در کلاس enum فراخوانی میکنیم تغییر دهیم
<select name=”roles”>
@foreach(UserRoles::asSelectArray() as $role)
<option value=”{{ $role->value }}”>{{ $role->name }}</option>
@endforeach
</select>
در حالی که این ویژگی نسبتاً تازه وارد PHP شده است ، enums و attribute ها افزوده های عالی به زبان هستند و پشتیبانی بومی را برای بسیاری از موارد استفاده رایج فراهم می کنند.