التعدادات (PHP 8.1)
جزء من قسم Object Oriented Programming في رحلة PHP على Coddy — الدرس 59 من 91.
قبل PHP 8.1، كان تمثيل مجموعة ثابتة من القيم مثل الحالات أو الأنواع يعني استخدام ثوابت الفئات (class constants) أو السلاسل النصية السحرية (magic strings) - وكلاهما أساليب عرضة للأخطاء. توفر Enums (التعدادات) طريقة صحيحة لتعريف نوع يمكنه فقط الاحتفاظ بقيم محددة مسبقاً.
قم بتعريف enum باستخدام الكلمة المفتاحية enum:
<?php
enum Status {
case Pending;
case Active;
case Completed;
}
$status = Status::Active;
echo $status->name;
المخرجات:
Activeيمكن للتعدادات (Enums) أن تحتوي أيضاً على قيم مدعومة (backed values) - وهي قيم نصية أو صحيحة مرتبطة بكل حالة. هذا مفيد عند تخزين التعدادات في قواعد البيانات أو واجهات برمجة التطبيقات (APIs):
<?php
enum Status: string {
case Pending = 'pending';
case Active = 'active';
case Completed = 'completed';
}
$status = Status::Active;
echo $status->value;
المخرجات:
activeتوفر التعدادات المدعومة (Backed enums) دالة from() لإنشاء تعداد من قيمته، ودالة tryFrom() التي تعيد null بدلاً من رمي خطأ للقيم غير الصالحة:
<?php
$status = Status::from('active'); // يعيد Status::Active
$invalid = Status::tryFrom('unknown'); // يعيد null
يمكن أن تحتوي التعدادات (Enums) أيضاً على أساليب (methods)، مما يجعلها قوية لتغليف المنطق المرتبط بها. وهي تعمل بسلاسة مع تلميحات النوع (type hints)، مما يضمن أن دوالك لا تقبل إلا القيم الصالحة - فلا داعي بعد الآن للتحقق مما إذا كانت السلسلة النصية (string) تطابق الخيارات المتوقعة.
التحدي
سهللنقم ببناء نظام لإدارة الطلبات يستخدم التعدادات (enums) لتمثيل حالات الطلب بطريقة آمنة من حيث النوع (type-safe). بدلاً من الاعتماد على السلاسل النصية التي قد تُكتب بشكل خاطئ أو تكون غير صالحة، ستقوم بإنشاء تعداد مدعوم (backed enum) يربط كل حالة بقيمة مناسبة لقاعدة البيانات.
ستقوم بتنظيم الكود الخاص بك عبر ثلاثة ملفات:
OrderStatus.php— أنشئ تعداداً مدعوماً بسلسلة نصية يسمىOrderStatusمع أربع حالات:Pendingمدعومة بـ'pending'Processingمدعومة بـ'processing'Shippedمدعومة بـ'shipped'Deliveredمدعومة بـ'delivered'
label()تُرجع وصفاً قابلاً للقراءة لكل حالة:- Pending تُرجع
"Awaiting confirmation" - Processing تُرجع
"Being prepared" - Shipped تُرجع
"On the way" - Delivered تُرجع
"Order complete"
Order.php— أنشئ فئةOrderتستخدم التعداد. قم بتضمين ملف OrderStatus. يجب أن تقوم الفئة بما يلي:- قبول معرف الطلب (string) و
OrderStatusفي منشئ الفئة (constructor) باستخدام خاصية constructor promotion - امتلاك دالة
getInfo()تُرجع"Order [id]: [status label]" - امتلاك دالة
getStatusValue()تُرجع القيمة المدعومة للحالة (مفيدة لتخزين قاعدة البيانات)
- قبول معرف الطلب (string) و
main.php— قم بتضمين ملف Order. ستتلقى مدخلين: معرف الطلب وسلسلة نصية للحالة (مثل"shipped"). استخدمtryFrom()لتحويل السلسلة النصية المدخلة بأمان إلى تعدادOrderStatus. إذا كانت الحالة صالحة، فقم بإنشاءOrderواطبع سطرين:- نتيجة
getInfo() - نتيجة
getStatusValue()
"Invalid status".- نتيجة
يوضح هذا التحدي كيف توفر التعدادات أماناً للنوع — حيث لا يمكن لفئة Order الخاصة بك إلا قبول حالات صالحة، وتسمح لك دالة tryFrom() بالتعامل بأمان مع مدخلات المستخدم دون المخاطرة بقيم غير صالحة.
ورقة مرجعية
توفر التعدادات (Enums) طريقة آمنة من حيث النوع لتعريف مجموعة ثابتة من القيم. قم بتعريف التعداد باستخدام الكلمة المفتاحية enum:
<?php
enum Status {
case Pending;
case Active;
case Completed;
}
$status = Status::Active;
echo $status->name; // المخرجات: Active
تربط التعدادات المدعومة (Backed enums) قيمًا نصية أو صحيحة بكل حالة:
<?php
enum Status: string {
case Pending = 'pending';
case Active = 'active';
case Completed = 'completed';
}
$status = Status::Active;
echo $status->value; // المخرجات: active
استخدم from() لإنشاء تعداد من قيمته، أو tryFrom() التي تعيد null للقيم غير الصالحة:
<?php
$status = Status::from('active'); // تعيد Status::Active
$invalid = Status::tryFrom('unknown'); // تعيد null
يمكن أن تحتوي التعدادات على دوال (methods) لتغليف المنطق البرمجي المرتبط بها:
<?php
enum Status: string {
case Pending = 'pending';
case Active = 'active';
public function label(): string {
return match($this) {
self::Pending => 'Awaiting',
self::Active => 'In Progress',
};
}
}
جرّب بنفسك
<?php
require_once 'Order.php';
// قراءة المدخلات
$orderId = trim(fgets(STDIN));
$statusString = trim(fgets(STDIN));
// TODO: استخدم OrderStatus::tryFrom() لتحويل سلسلة الحالة بأمان إلى enum
// تعيد tryFrom() القيمة null إذا كانت القيمة غير صالحة
// TODO: إذا كانت الحالة صالحة، قم بإنشاء Order واطبع:
// - نتيجة getInfo()
// - نتيجة getStatusValue()
// TODO: إذا كانت الحالة غير صالحة، اطبع "Invalid status"
?>يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس Object Oriented Programming
1أساسيات OOP
الملفات الخارجيةمقدمة في OOPClasses مقابل Objectsالكلمة المفتاحية $thisالـ Methodsالـ Propertiesالمنشئ (__construct)الهادم (__destruct)مراجعة - آلة حاسبة بسيطة4الوراثة
الوراثة الأساسيةالكلمة المفتاحية parent::إعادة تعريف الدوال (Method Overriding)الكلمة المفتاحية finalالأصناف المجردة (Abstract Classes)مراجعة - هيكلية الموظفين7التغليف (Encapsulation)
العام، المحمي، الخاص (Public, Protected, Private)نظرة متعمقة على معدلات الوصولدوال Getters و Settersإخفاء المعلوماتميزة Constructor Promotion (8.0)مراجعة - نظام سجلات الطلاب10مفاهيم البرمجة كائنية التوجه المتقدمة
التركيب مقابل الوراثةحقن التبعيةالأصناف المجهولةالتعدادات (PHP 8.1)الألياف (PHP 8.1)تعمق في استنساخ الكائناتالمولدات والمكررات13أنماط التصميم - الجزء الثاني
نمط الأمرنمط المحولنمط المزيننمط طريقة القالبنمط الحالةنمط التركيبنمط المستودع2مساحات الأسماء والتحميل التلقائي
مقدمة إلى مساحات الأسماءالكلمة المفتاحية useمعيار التحميل التلقائي PSR-4أداة التحميل التلقائي Composerملخص - مشروع منظم5الواجهات والعقود
مقدمة إلى الواجهاتتنفيذ الواجهاتتنفيذ واجهات متعددةالواجهة مقابل الـ Abstract Classالـ Type Hinting مع الواجهاتملخص - حاسبة الأشكال8الميثودات السحرية (Magic Methods)
مقدمة في الميثودات السحرية__toString و __debugInfo__get, __set, __isset, __unset__call و __callStatic__clone واستنساخ الكائنات__serialize و __unserializeمراجعة - Custom Collection3خصائص الكلاس
خصائص الـ Instance مقابل الخصائص الساكنة (Static)الثوابت في الكلاساتالدوال والخصائص الساكنة (Static)الخصائص الخاصة (Private) والمحمية (Protected)خصائص للقراءة فقط (Readonly) في PHP 8.1مراجعة - مدير الحساب البنكي6تعدد الأشكال (Polymorphism)
مراجعة إعادة تعريف الدوال (Method Overriding)تعدد الأشكال عبر الـ Interfacesتلميح النوع (Type Hinting) وأنواع الاتحاد (Union Types)الربط الاستاتيكي المتأخر (Late Static Binding)ملخص - معالج الدفع (Payment Processor)