الباني في PHP تابع اسمه __construct(). تستدعيه PHP تلقائيًا عندما تكتب new ClassName(...)، وتصبح الوسائط بين القوسين معاملاته، فيبدأ الكائن حياته وقيمه مضبوطة أصلًا.
دون باني ستنشئ كائنًا فارغًا وتضبط كل خاصية بعده، ولن يمنعك شيء من نسيان إحداها. ومع الباني، تكون new User() دون وسائط خطأ ArgumentCountError.
ترقية خصائص الباني
تعريف خاصية، وذكرها معاملًا، وإسناد $this->name = $name يكرر كل اسم ثلاث مرات. ومنذ PHP 8.0، تفعل كلمة رؤية أمام معامل الباني الثلاثة معًا:
يمكن أن يكون المعامل المرقّى أيضًا readonly (public readonly string $id)، وهي أقصر طريقة لكتابة كائن قيمة غير قابل للتغيير. ويمكنك المزج بين المعاملات المرقّاة والعادية، ويظل جسم الباني قادرًا على احتواء شيفرة تعمل بعد إسناد الخصائص المرقّاة.
القيم الافتراضية والوسائط المسماة
تأخذ معاملات الباني قيمًا افتراضية مثل أي دالة. وتأتي المعاملات ذات القيم الافتراضية بعد الإلزامية. ومع الوسائط المسماة (PHP 8.0) يستطيع المستدعي القفز إلى الخيار الذي يريده بدل تكرار كل قيمة افتراضية قبله:
شغّله: تحتوي المخرجات HTML، لذا يعرض تبويب Page الأزرار الثلاثة، ويعرض تبويب Output الوسوم التي طبعتها PHP. لاحظ الأقواس في (new Button('Save'))->render(): منذ PHP 8.4 هي اختيارية، لكن PHP 8.3 تحتاج إليها.
التحقق من الوسائط في الباني
لا يستطيع الباني إعادة false أو رمز خطأ: يُتجاهل كل ما يعيده. لرفض المُدخلات الخاطئة، ارمِ استثناءً. عندها لا يُنشأ الكائن أبدًا، فيستطيع بقية البرنامج الوثوق بكل Temperature يتلقاها.
تشرح صفحة try catch التقاط هذه الاستثناءات بمزيد من التفصيل.
عدة بوانٍ بتوابع مصنع ساكنة
ليس في PHP تحميل زائد للبواني: صنف واحد، __construct واحد. وعندما يمكن بناء الكائن من مُدخلات مختلفة (نص تاريخ، مصفوفة، طابع زمني)، أضف توابع ساكنة مسماة تجهّز الوسائط وتستدعي new static(...). وجعل الباني private يجبر الجميع على المرور عبر توابع المصنع.
صار new Color(1, 2, 3) من خارج الصنف يرمي Error ("Call to private Color::__construct() from global scope"). وتشرح صفحة static لماذا تُستخدم new static هنا بدل new self.
استدعاء باني الأب بـ parent::__construct
عندما يعرّف صنف ابن بانيه الخاص، لا يعمل باني الأب من تلقاء نفسه. استدعه بـ parent::__construct(...)، عادة أولًا، حتى تُضبط خصائص الأب قبل أن يضيف الابن خصائصه:
إذا لم يكن للابن باني أصلًا، تستخدم PHP باني الأب، فتمرر new Truck('Volvo') وسائطها مباشرة إلى Vehicle::__construct. مزيد عن هذا في الوراثة.
نسيان parent::__construct
لا ينتج هذا الخطأ أي رسالة في السطر الذي يحدث فيه. يعمل باني الابن، وتبقى خصائص الأب ذات الأنواع غير مهيأة، ويفشل البرنامج لاحقًا، حيثما تحدث أول قراءة:
أضف parent::__construct(); سطرًا أول في Post::__construct وشغّله مرة أخرى: يطبع التاريخ. وهناك تابع ذو صلة، __destruct()، يعمل عندما يختفي آخر مرجع إلى كائن أو ينتهي السكربت. ونادرًا ما تحتاجه في الشيفرة اليومية، لأن PHP تغلق الملفات وتحرر الذاكرة بنفسها في نهاية كل طلب.
الأسئلة الشائعة
ما هو __construct في PHP؟
__construct() هو الباني: تابع تستدعيه PHP تلقائيًا مباشرة بعد أن تنشئ new الكائن. الوسائط التي تمررها إلى new User('Ada', 36) تُمرَّر إلى __construct(string $name, int $age)، الذي يخزّنها عادة في خصائص.
ما هي ترقية خصائص الباني في PHP؟
منذ PHP 8.0، وضع كلمة رؤية على معامل الباني يعرّف الخاصية ويسندها في خطوة واحدة: public function __construct(private string $name) {} مماثل لتعريف private string $name; وكتابة $this->name = $name; في الجسم.
هل يمكن أن يكون لصنف PHP عدة بوانٍ؟
لا. ليس في PHP تحميل زائد للتوابع، لذا للصنف __construct واحد. استخدم معاملات اختيارية بقيم افتراضية، أو أضف توابع مصنع ساكنة مثل public static function fromArray(array $data): static تستدعي new static(...) بالوسائط الصحيحة.
هل يُستدعى باني الصنف الأب تلقائيًا في PHP؟
فقط عندما لا يكون للصنف الابن باني خاص به. إذا عرّف الابن __construct، فلا يعمل باني الأب ما لم تستدعِ parent::__construct(...) بنفسك، عادة في السطر الأول.
هل يمكن لباني PHP أن يعيد قيمة؟
لا. تعطيك new الكائن دائمًا، ويُتجاهل كل ما تعيده __construct. للإبلاغ عن مشكلة، ارمِ استثناءً من الباني، مثل throw new InvalidArgumentException('Age must be positive').