Generics في PHP: لماذا هي ضرورية وكيفية استخدامها مع أمثلة

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

Generics في PHP: لماذا هي ضرورية وكيفية استخدامها



التطوير الحديث في PHP لا يتطلب السرعة فحسب، بل يتطلب أيضًا موثوقية الكود. من الأدوات التي تساعد في تحقيق هذا الهدف هي Generics (الأنواع العامة). على الرغم من أن PHP هي لغة ذات كتابة ديناميكية، إلا أنه مع إصدار PHP 7.0 وما فوق، وخاصة PHP 8.0، أصبحت الكتابة الثابتة متاحة ومطلوبة. تسمح Generics بكتابة هياكل بيانات أكثر مرونة وقابلة لإعادة الاستخدام وآمنة، مثل المجموعات والمكدسات والطوابير والمستودعات، دون فقدان معلومات الأنواع.



في هذه المقالة، سنشرح بالتفصيل ما هي Generics في PHP، ولماذا هي ضرورية، وكيفية استخدامها بشكل صحيح عمليًا، وسنستعرض أمثلة كود محددة.



ما هي Generics ولماذا هي ضرورية؟



Generics (الأنواع العامة) هي آلية تسمح بتمييز الفئات والواجهات والـ traits والدوال بنوع البيانات. بدلاً من كتابة تطبيق منفصل لكل نوع (مثل IntegerList و StringList و UserList)، تقوم بإنشاء فئة عامة واحدة List<T>، حيث T هو placeholder (بديل) لنوع محدد سيتم تمريره عند الاستخدام.



لماذا هذا ضروري؟

  • أمان الأنواع: يمكن لبيئة التطوير المتكاملة (IDE) والمحللات الثابتة (Psalm, PHPStan) التحقق من أن المجموعة تحتوي فقط على عناصر من نوع واحد، مما يمنع الأخطاء في مرحلة التطوير.
  • تقليل تكرار الكود: لست بحاجة لكتابة نفس الفئة لأنواع بيانات مختلفة.
  • تحسين قابلية القراءة: يصبح الكود موثقًا ذاتيًا — يمكنك رؤية أنواع البيانات المتوقعة فورًا.
  • زيادة الأداء: على الرغم من أن PHP نفسها لا تستخدم Generics على مستوى الآلة الافتراضية (مثل Java أو C#)، إلا أن المحللات الثابتة تساعد في العثور على الأخطاء المحتملة قبل تنفيذ الكود.


كيفية استخدام Generics في PHP؟ الصيغة والأمثلة



بدءًا من PHP 8.0، تم تقديم دعم Generics على مستوى التعليقات التوضيحية (docblock) وجزئيًا على مستوى الكود (لـ variadic arguments). الدعم الكامل على مستوى الصيغة متوقع في الإصدارات المستقبلية، ولكن يمكنك بالفعل استخدام Generics بشكل فعال باستخدام PHPDoc والمحللات الثابتة.



1. الصيغة الأساسية مع PHPDoc



الطريقة الأكثر شيوعًا هي استخدام التعليقات التوضيحية @template و @param/@return مع تحديد النوع العام.



<?php

/** * @template T */class Collection { /** @var array<T> */ private array $items;

/** * @param T $item */ public function add($item): void { $this->items[] = $item; }

/** * @return T|null */ public function get(int $index) { return $this->items[$index] ?? null; }}

// مثال على الاستخدام$intCollection = new Collection();$intCollection->add(42);// $intCollection->add('string'); // خطأ من المحلل الثابت

$userCollection = new Collection();$userCollection->add(new User());// $userCollection->add(123); // خطأ?>


في هذا المثال، @template T يعلن عن نوع عام. @param T $item و @return T|null يخبران المحلل بأن نوع العناصر يجب أن يكون متسقًا.



2. قيود الأنواع (bounded generics)



يمكنك تقييد الأنواع التي يمكن استخدامها كمعامل. يتم ذلك باستخدام @extends أو @implements.



<?php

/** * @template T of \\Stringable */class StringableCollection { /** @var array<T> */ private array $items;

/** * @param T $item */ public function add($item): void { $this->it

المدونات

توصيات الكتب