استخدام سمات متعددة
جزء من قسم البرمجة كائنية التوجه في رحلة PHP على Coddy. الدرس 52 من 91.
تكون السمة الواحدة مفيدة، لكن القوة الحقيقية تظهر عندما تجمع عدة سمات في class واحدة. يتيح لك PHP تضمين العدد الذي تحتاج إليه من السمات، مما يمنح class لديك إمكانات من عدة مصادر في آنٍ واحد.
لاستخدام سمات متعددة، ما عليك سوى سردها مفصولة بفواصل بعد الكلمة المفتاحية use:
<?php
trait Timestampable {
public function getTimestamp(): string {
return date('Y-m-d H:i:s');
}
}
trait Identifiable {
private string $id;
public function generateId(): void {
$this->id = uniqid('id_');
}
public function getId(): string {
return $this->id;
}
}
class Post {
use Timestampable, Identifiable;
public function __construct(public string $title) {
$this->generateId();
}
}
$post = new Post("Hello World");
echo $post->getId() . " - " . $post->getTimestamp();
الناتج:
id_6789abc123 - 2024-01-15 10:30:00تحتوي فئة Post الآن على أساليب من كلتا السمتين. تساهم كل سمة بوظائفها الخاصة - توفر Timestampable أساليب مرتبطة بالوقت، بينما تتولى Identifiable التعامل مع المعرّفات الفريدة. يحافظ هذا النهج على تركيز كل سمة على مسؤولية واحدة، مما يجعل شفرتك أكثر نمطية وقابلية لإعادة الاستخدام.
ماذا يحدث عندما يكون لدى سمتين methods بالاسم نفسه؟ هذه حالة تعارض سنستكشفها في الدرس التالي.
التحدي
سهللنَبْنِ نظامًا لإدارة المنتجات يجمع بين سمات متعددة لمنح المنتجات إمكانات التسعير وإدارة المخزون. ستتولى كل سمة مسؤولية واحدة، وسيحصل صنف المنتج على الوظائف من كلتيهما.
ستنظّم الشيفرة عبر ثلاثة ملفات:
Priceable.php: أنشئ سمة باسمPriceableتتولى وظائف التسعير. يجب أن تحتوي السمة على:- خاصية
$priceخاصة (من النوع float) - دالة
setPrice(float $price)تخزّن السعر - دالة
getPrice()تُرجع السعر - دالة
getFormattedPrice()تُرجع السعر منسقًا بالشكل"$[price]"مع منزلتين عشريتين
- خاصية
Stockable.php: أنشئ سمة باسمStockableتدير المخزون. يجب أن تحتوي السمة على:- خاصية
$stockخاصة (من النوع integer) - دالة
setStock(int $quantity)تخزّن كمية المخزون - دالة
getStock()تُرجع المخزون الحالي - دالة
isInStock()تُرجعtrueإذا كان المخزون أكبر من 0، وfalseخلاف ذلك
- خاصية
main.php: ضمّن ملفي السمتين وأنشئ صنفًا باسمProductيستخدم سمتيPriceableوStockable. استخدم ترقية المُنشئ لتعريف خاصية عامة باسم$name. يجب أن يقبل المُنشئ أيضًا سعرًا وكمية مخزون، مع استخدام دوال السمتين لتعيينهما.ستتلقى ثلاث قيم إدخال: اسم منتج، وسعرًا، وكمية مخزون. أنشئ منتجًا بهذه القيم واطبع أربعة أسطر:
- اسم المنتج
- السعر المنسق (باستخدام
getFormattedPrice()) - كمية المخزون
"Available"إذا كان المنتج متوفرًا في المخزون، أو"Out of stock"إذا لم يكن كذلك
يوضح هذا كيفية عمل السمات المتعددة معًا. يكتسب صنف Product إمكانات التسعير من سمة، وإدارة المخزون من سمة أخرى، مع إبقاء كل مسؤولية منفصلة بوضوح ودمجها في منتج متكامل الوظائف.
جرّب بنفسك
<?php
require_once 'Priceable.php';
require_once 'Stockable.php';
// TODO: أنشئ صنف Product يستخدم كلاً من سمتي Priceable و Stockable
// استخدم ترقية المُنشئ للخاصية العامة $name
// يجب أن يقبل المُنشئ name و price و stock، ويستخدم طرق السمات لتعيين السعر والمخزون
class Product {
// TODO: استخدم السمات هنا
// TODO: نفّذ المُنشئ مع ترقية المُنشئ لـ $name
// وعيّن السعر والمخزون باستخدام طرق السمات
}
// اقرأ الإدخال
$name = trim(fgets(STDIN));
$price = floatval(trim(fgets(STDIN)));
$stock = intval(trim(fgets(STDIN)));
// TODO: أنشئ مثيلاً من Product بقيم الإدخال
// TODO: اطبع اسم المنتج
// TODO: اطبع السعر المنسّق باستخدام getFormattedPrice()
// TODO: اطبع كمية المخزون
// TODO: اطبع "Available" إذا كان متوفراً في المخزون، أو "Out of stock" إذا لم يكن
?>يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
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)9السمات (Traits)
مقدمة إلى السماتاستخدام سمات متعددةحل تعارض السماتالدوال المجردة في السماتالسمات مقابل الوراثةتدرّب بنفسك: مترجم PHP عبر الإنترنت