في هذا الدرس 6تصفّح المواضيع
تُعرّف التعدادات (enum) المضافة في PHP 8.1 نوع بيانات مغلقاً وصارماً يقتصر على مجموعة محددة من الحالات المسماة (case)، بدلاً من النصوص العشوائية القابلة للخطأ الإملائي.
- عرّف الحالات المسموحة داخل
enumباستخدام الكلمة المفتاحيةcase(مثلcase Pending;). - كل حالة داخل التعداد تمثل كائناً وحيداً (Singleton) من نوع هذا التعداد، لذا تقارن الحالات بالمطابقة الصارمة
===. - تمتلك كل حالة تلقائياً خاصية للقراءة فقط باسم
$case->nameتحتوي على الاسم النصي للحالة.
تحدد الدالة assignSla() نوع المعامل كـ TicketPriority، مما يجعل تمرير أي قيمة غير صالحة مستحيلاً.
<?php
enum TicketPriority {
case Low;
case Medium;
case Critical;
}
function assignSla(TicketPriority $p): string {
return $p === TicketPriority::Critical ? "1 Hour SLA" : "24 Hour SLA";
}
$current = TicketPriority::Critical;
echo $current->name . " -> " . assignSla($current) . "\n";
عندما تحتاج لتخزين التعداد في قاعدة البيانات أو إرساله عبر النماذج وملفات JSON، عرّف تعداداً مدعوماً بقيم قياسية (Backed Enum) من النوع string أو int.
- حدد نوع القيمة المدعومة بعد نقطتين رأسيتين (
enum OrderStatus: string) وأسند قيمة فريدة لكل حالة. - اقرأ القيمة النصية أو الرقمية للحالة عبر الخاصية المدمجة
$case->value. - حوّل مدخلات المستخدم أو قاعدة البيانات بأمان إلى حالة تعداد عبر الدالة
OrderStatus::tryFrom($raw)التي تُرجعnullعند عدم التطابق.
تُرجع tryFrom("shipped") الحالة OrderStatus::Shipped، بينما تُرجع tryFrom("unknown_state") القيمة null بأمان تام.
<?php
enum OrderStatus: string {
case Pending = "pending";
case Shipped = "shipped";
case Cancelled = "cancelled";
}
$valid = OrderStatus::tryFrom("shipped");
$invalid = OrderStatus::tryFrom("unknown_state");
echo "Valid : " . ($valid?->name ?? "NULL") . " ({$valid?->value})\n";
echo "Invalid : " . ($invalid?->name ?? "NULL (Safe Fallback)") . "\n";
التعدادات في PHP كائنات غنية المزايا؛ فيمكنها تطبيق الواجهات (implements)، وتعريف الدوال التي تستخدم $this وتعبير match($this).
- داخل دالة التعداد، تشير الكلمة
$thisإلى حالة التعداد المحددة التي تم استدعاء الدالة عليها. - دمج دوال التعداد مع تعبير
match($this)يجمع العناوين والألوان والصلاحيات في مكان واحد منظم. - لا يمكن للتعدادات احتواء خصائص متغيرة ولا يمكنها الوراثة عبر
extends.
يطبق التعداد Role الواجهة HasBadge ويربط كل حالة بلون الشارة المقابل عبر تعبير match($this).
<?php
interface HasBadge { public function badgeColor(): string; }
enum Role: string implements HasBadge {
case Admin = "admin";
case Viewer = "viewer";
public function badgeColor(): string {
return match ($this) {
self::Admin => "purple",
self::Viewer => "slate",
};
}
}
echo Role::Admin->value . " badge=" . Role::Admin->badgeColor() . "\n";
إن وسم الخاصية بـ readonly (في PHP 8.1) أو وسم الصنف بالكامل كـ readonly class (في PHP 8.2+) يضمن إسناد قيم الخصائص مرة واحدة فقط ومنع تعديلها لاحقاً.
- كتابة
readonly class TransferRequestتجعل كل خاصية معلنة داخل الصنف للقراءة فقط (readonly) تلقائياً. - يجب إلزاماً تحديد نوع البيانات لكل خاصية داخل الصنف
readonly(ويمكن استخدامmixedعند تعدد الأنواع). - دمج
readonly classمع ترقية خصائص الباني ينشئ كائنات نقل بيانات غير قابلة للتعديل (DTOs) في بضعة أسطر نظيفة.
بمجرد إنشاء الكائن $dto، يمنع محرك PHP أي محاولة لتغيير قيم خصائصه مثل $dto->amountCents = 0; في أي مكان بالكود.
<?php
readonly class PaymentDto {
public function __construct(
public string $txId,
public int $amountCents,
public string $currency = "SAR"
) {}
}
$dto = new PaymentDto("TX-900", 25000);
echo "{$dto->txId}: {$dto->amountCents} {$dto->currency}\n";
يقدّم PHP 8.4 خطافات الخصائص الأصلية (get وset) والرؤية غير المتماثلة (public private(set)) للاستغناء عن دوال القراءة والتعديل التقليدية المكررة.
- أرفق خطاف
setمباشرة بالخاصية (مثلpublic string $email { set => strtolower(trim($value)); }) لتنقية القيمة تلقائياً عند كل إسناد. - أنشئ خاصية افتراضية محسوبة باستخدام خطاف
getفقط دون حجز مساحة تخزين إضافية في الكائن. - استخدم الرؤية غير المتماثلة
public private(set) int $points = 0;لكي يُسمح بقراءة الخاصية من الخارج مع حصر تعديلها داخل الصنف نفسه فقط.
إسناد $p->name يشغل خطاف set في PHP 8.4 تلقائياً لتهذيب الاسم، بينما تُقرأ $loyaltyPoints علناً ولا تُعدل إلا عبر دوال الصنف.
<?php
class CustomerProfile {
public string $name {
set => ucwords(strtolower(trim($value)));
}
public private(set) int $loyaltyPoints = 100;
public function addPoints(int $pts): void { $this->loyaltyPoints += $pts; }
}
$p = new CustomerProfile();
$p->name = " tariq al-ali ";
$p->addPoints(50);
echo "{$p->name} | Points: {$p->loyaltyPoints}\n";
اجمع بين التعدادات (Enums) والأصناف للقراءة فقط (Readonly) وخطافات الخصائص والرؤية غير المتماثلة لبناء نماذج بيانات حديثة ومحمية ذاتياً في PHP 8.4.
- استخدم التعدادات المدعومة (Backed Enums) لتمثيل الحالات المحدودة كالأدوار والعملات وحالات الطلبات.
- استخدم
readonly classلكائنات القيم الثابتة وطلبات API وبيانات الأحداث التي لا تتغير بعد إنشائها. - استخدم خطافات الخصائص و
public private(set)في PHP 8.4 للكيانات القابلة للتحديث المنضبط عبر دوال الصنف.
يجمع الصنف SubscriptionSnapshot بين readonly class والتعداد المدعوم PlanTier لضمان سلامة النوع والحالة معاً.
| الميزة البرمجية | إصدار PHP | حالة الاستخدام الأساسية |
|---|---|---|
Pure & Backed enum | PHP 8.1+ | Fixed set of states, roles, or types (tryFrom) |
readonly properties | PHP 8.1+ | Write-once immutable object properties |
readonly class | PHP 8.2+ | Full immutable DTOs and Value Objects |
Property Hooks (get / set) | PHP 8.4+ | Inline normalization and computed properties |
Asymmetric Visibility (public private(set)) | PHP 8.4+ | Public read access with private/protected mutation |
<?php
enum PlanTier: string { case Free = "free"; case Pro = "pro"; }
readonly class SubscriptionSnapshot {
public function __construct(public string $account, public PlanTier $tier) {}
}
$sub = new SubscriptionSnapshot("acc_402", PlanTier::from("pro"));
echo "{$sub->account} is on {$sub->tier->name} ({$sub->tier->value})\n";
ملخص الدرس
حصاد الدرسمراجعة مركّزة لأهم المفاهيم والقواعد الهندسية التي أتقنتها في هذا الدرس قبل التطبيق العملي
ماذا تعلّمت في هذا الدرس؟
اجمع بين التعدادات (Enums) والأصناف للقراءة فقط (Readonly) وخطافات الخصائص والرؤية غير المتماثلة لبناء نماذج بيانات حديثة ومحمية ذاتياً في PHP 8.4. استخدم التعدادات المدعومة (Backed Enums) لتمثيل الحالات المحدودة كالأدوار والعملات وحالات الطلبات. استخدم readonly class لكائنات القيم الثابتة وطلبات API وبيانات الأحداث التي لا تتغير بعد إنشائها. استخدم خطافات الخصائص وpublic private(set) في PHP 8.4 للكيانات القابلة للتحديث المنضبط عبر دوال الصنف.
سجّل الدخول لحفظ تقدمك
تابع إنجاز المواضيع والمصطلحات والمهام، وكمّل من آخر خطوة على أي جهاز.
المصطلحات4
راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.
- 01 Enums & Readonly Enums و Readonly
- ابنِ نماذج بيانات قوية في PHP 8.4 باستخدام التعدادات Enums والأصناف للقراءة فقط readonly وخطافات الخصائص الحديثة.
- للمراجعة
- 02 Declaring Pure Enums in PHP 8 تعريف التعدادات الصرفة Pure Enums
- المفهوم الأساسي لقسم تعريف التعدادات الصرفة Pure Enums في لغة PHP الحديثة.
- للمراجعة
- 03 Backed Enums with from and tryFrom التعدادات المدعومة بقيم ودالتا from و tryFrom
- الصياغة البرمجية والتطبيق العملي المباشر لقسم التعدادات المدعومة بقيم ودالتا from و tryFrom.
- للمراجعة
- 04 Adding Methods and Interfaces to Enums إضافة الدوال والواجهات داخل Enums
- قواعد التحقق وأفضل الممارسات القياسية الخاصة بقسم إضافة الدوال والواجهات داخل Enums.
- للمراجعة
لا توجد بطاقات تطابق البحث والتصفية.
اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.
الاختصارات4
راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.
- 01 PHP PHP
- PHP: Hypertext Preprocessor
- لغة البرمجة النصية على جانب الخادم لبناء تطبيقات الويب الديناميكية وواجهات البرمجة.
- للمراجعة
- 02 CLI CLI
- Command-Line Interface
- واجهة سطر الأوامر التي تتيح تشغيل ملفات PHP مباشرة عبر الطرفية.
- للمراجعة
- 03 FPM FPM
- FastCGI Process Manager
- مدير عمليات FastCGI عالي الأداء لمعالجة طلبات خادم الويب في PHP.
- للمراجعة
- 04 HTML HTML
- HyperText Markup Language
- لغة الترميز القياسية التي يولدها محرك PHP ويرسلها إلى متصفح العميل بعد التنفيذ.
- للمراجعة
لا توجد بطاقات تطابق البحث والتصفية.
اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.
مهامك قبل الاختبار
خطوة صغيرة كل مرة. وإنجاز تقدر ترجع له.
-
أنشئ ملف PHP محلياً ونفّذ المثال البرمجي المشروح في قسم تعريف التعدادات الصرفة Pure Enums للتحقق من المخرجات.
-
بدّل بين الحالات الثلاث في المحاكي التفاعلي ضمن قسم التعدادات المدعومة بقيم ودالتا from و tryFrom وقارن مخرجات التنفيذ.
تأشير المهمة إقرار منك بإتمامها، وليس تصحيحًا آليًا للكود. يُحفظ تقدمك في حسابك.
اختبر فهمك.
ووصلها للإتقان.
كل سؤال خطوة لقدّام. اختار، اكتب كود، وشوف نتيجتك فورًا.
أكمل المهام، واجمع كل الإجابات الصحيحة. أقل من 100%؟ راجع وأعد المحاولة.
الأسئلة متاحة للاطلاع. سجّل الدخول للتفاعل وحفظ تقدمك.
لمحة عن التحدي8 أسئلة تنتظرك +
ما الفرق بين التعداد الصرف (Pure Enum) والتعداد المدعوم بقيم (Backed Enum) في PHP 8.1+؟
تحدد التعدادات المدعومة النوع : int أو : string وتوفر الخاصية $case->value ودالتي from() وtryFrom().
ماذا تُرجع الدالة OrderStatus::tryFrom("invalid_code") إذا لم تطابق القيمة أي حالة في التعداد المدعوم OrderStatus؟
تُرجع tryFrom() القيمة null عند عدم وجود تطابق، بينما تطلق from() خطأ ValueError.
أي عبارة مما يلي صحيحة حول الدوال والخصائص داخل التعداد (Enum) في PHP؟
يُسمح للتعدادات بالدوال والثوابت والواجهات، ويُمنع فيها تعريف الخصائص المتغيرة.
ماذا يفعل وسم الصنف بالكلمة المفتاحية readonly (مثل readonly class InvoiceDto) في PHP 8.2+؟
يجعل الصنف جميع خصائصه قابلة للإسناد مرة واحدة فقط ويمنع الخصائص الديناميكية.
في خطاف الخاصية في PHP 8.4: public string $code { set => strtoupper($value); }، ماذا يمثل المتغير $value؟
يمثل $value القيمة الممررة عند الإسناد، وتُخزن نتيجة التعبير داخل الخاصية.
ماذا تفرض صيغة الرؤية غير المتماثلة public private(set) int $balance = 0; في PHP 8.4؟
تسمح public بالقراءة العامة، بينما تقصر private(set) صلاحية الكتابة والتعديل على داخل الصنف نفسه.
ما الدالة الثابتة المدمجة التي تُرجع مصفوفة بجميع الحالات المعرّفة داخل أي تعداد Enum؟
يطبق كل تعداد في PHP تلقائياً الواجهة UnitEnum التي توفر الدالة الثابتة cases().
لماذا يجب أن تحمل كل خاصية داخل الصنف readonly نوع بيانات صريحاً (مثل string أو int أو mixed)؟
تبدأ الخصائص المحددة النوع بحالة غير مهيأة (uninitialized) حتى أول إسناد، وهو شرط عمل readonly.