مقدمة: لماذا هذا السؤال يربك كل مطور PHP تقريباً؟
\n\nإذا كنت قد كتبت بلغة PHP بأسلوب البرمجة كائنية التوجه، فلا بد أنك واجهت المعضلة: متى نستخدم self ومتى نستخدم $this؟ هذا السؤال هو واحد من أكثر الأسئلة شيوعاً على Stack Overflow (آلاف المشاهدات وعشرات الأصوات). يبدو الفرق واضحاً، لكن بمجرد التعمق، حتى المطورين ذوي الخبرة يبدأون في الخلط.
في هذه المقالة، سنقوم بترتيب الأمور بشكل منهجي. ستتعلم:
\n- \n
- ما الفرق الجوهري بين
selfو$this؛ \n - في أي الحالات يكون كل منهما إلزامياً؛ \n
- كيف يعمل الوراثة والسياقات الثابتة؛ \n
- وبالطبع، سترى أمثلة حقيقية للكود يمكنك تطبيقها فوراً. \n
هيا بنا نفهم الأمر مرة واحدة وإلى الأبد!
\n\nالقاعدة الأساسية: الثابت مقابل النسخة (الكائن)
\n\nأهم شيء يجب تذكره:
\n- \n
$this— يشير إلى الكائن الحالي (نسخة من الفئة). يعمل فقط في السياق غير الثابت. \n self— يشير إلى الفئة الحالية التي كُتب فيها الكود. يُستخدم للوصول إلى الخصائص الثابتة والثوابت والطرق الثابتة. \n
يبدو الأمر بسيطاً؟ دعنا نتحقق من ذلك بمثال.
\n\nمثال 1: فئة بسيطة
\n<?php\nclass Coffee\n{\n public static $type = 'أرابيكا';\n public $sugar = 2;\n\n public function info()\n {\n // $this — لخصائص الكائن\n echo "السكر: {$this->sugar} ملاعق.";\n\n // self — للخاصية الثابتة\n echo "نوع القهوة: " . self::$type;\n }\n}\n\n$cup = new Coffee();\n$cup->info(); // سيطبع: السكر: 2 ملاعق. نوع القهوة: أرابيكا\n?>\n\nكل شيء منطقي هنا: $this->sugar فريد لكل فنجان، بينما self::$type مشترك بين الجميع.
مكر الوراثة: self مقابل static
\n\nوهنا يبدأ الجزء المثير للاهتمام. يعتقد الكثيرون أن self يتصرف بشكل متعدد الأشكال، لكن هذا غير صحيح. self يشير دائماً إلى الفئة التي كُتب فيها، حتى لو قمت باستدعاء الطريقة من فئة فرعية.
إذا كنت بحاجة إلى أن يأخذ الكود في الاعتبار الفئة التي تم استدعاؤه منها (الربط الثابت المتأخر)، استخدم static.
مثال 2: الوراثة والمفاجأة
\n<?php\nclass Animal\n{\n public static $sound = '...';\n\n public static function speak()\n {\n // انتبه: self هو Animal، وليس Dog!\n echo self::$sound;\n }\n\n public static function speakCorrect()\n {\n // static هي الفئة التي استدعت الطريقة\n echo static::$sound;\n }\n}\n\nclass Dog extends Animal\n{\n public static $sound = 'هاو!';\n}\n\nDog::speak(); // سيطبع: ... (لأن self = Animal)\nDog::speakCorrect(); // سيطبع: هاو! (لأن static = Dog)\n?>\n\nهذا المثال هو سبب شائع للأخطاء. إذا كنت تكتب مكتبة وتتوقع أن تتمكن الفئات الفرعية من تجاوز الخصائص الثابتة، استخدم دائماً static بدلاً من self.
متى لا يمكن الاستغناء عن self؟
\n\nهناك حالات لا يعمل فيها $this ببساطة، ويكون self هو الخيار الوحيد:
- \n
- الطرق الثابتة: داخل طريقة تم تعريفها كـ
public static function، لا يوجد كائن، لذا$thisغير متاح. فقطself. \n - ثوابت الفئة: يتم الوصول إليها عبر
self::CONSTANT(أوClassName::CONSTANT). \n - الخصائص الثابتة:
self::$property. \n - داخل المُنشئ أو المُدمّر: على الرغم من أن
$thisمتاح هناك، إلا أنه من الأفضل استخدامselfللعمليات الثابتة.