self أو $this في PHP: متى نستخدم أيهما؟ شرح مع أمثلة

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

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

ابدأ الدورة

مقدمة: لماذا هذا السؤال يربك كل مطور PHP تقريباً؟

\n\n

إذا كنت قد كتبت بلغة PHP بأسلوب البرمجة كائنية التوجه، فلا بد أنك واجهت المعضلة: متى نستخدم self ومتى نستخدم $this؟ هذا السؤال هو واحد من أكثر الأسئلة شيوعاً على Stack Overflow (آلاف المشاهدات وعشرات الأصوات). يبدو الفرق واضحاً، لكن بمجرد التعمق، حتى المطورين ذوي الخبرة يبدأون في الخلط.

\n\n

في هذه المقالة، سنقوم بترتيب الأمور بشكل منهجي. ستتعلم:

\n
    \n
  • ما الفرق الجوهري بين self و $this؛
  • \n
  • في أي الحالات يكون كل منهما إلزامياً؛
  • \n
  • كيف يعمل الوراثة والسياقات الثابتة؛
  • \n
  • وبالطبع، سترى أمثلة حقيقية للكود يمكنك تطبيقها فوراً.
  • \n
\n\n

هيا بنا نفهم الأمر مرة واحدة وإلى الأبد!

\n\n

القاعدة الأساسية: الثابت مقابل النسخة (الكائن)

\n\n

أهم شيء يجب تذكره:

\n
    \n
  • $this — يشير إلى الكائن الحالي (نسخة من الفئة). يعمل فقط في السياق غير الثابت.
  • \n
  • self — يشير إلى الفئة الحالية التي كُتب فيها الكود. يُستخدم للوصول إلى الخصائص الثابتة والثوابت والطرق الثابتة.
  • \n
\n\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 مشترك بين الجميع.

\n\n

مكر الوراثة: self مقابل static

\n\n

وهنا يبدأ الجزء المثير للاهتمام. يعتقد الكثيرون أن self يتصرف بشكل متعدد الأشكال، لكن هذا غير صحيح. self يشير دائماً إلى الفئة التي كُتب فيها، حتى لو قمت باستدعاء الطريقة من فئة فرعية.

\n\n

إذا كنت بحاجة إلى أن يأخذ الكود في الاعتبار الفئة التي تم استدعاؤه منها (الربط الثابت المتأخر)، استخدم static.

\n\n

مثال 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.

\n\n

متى لا يمكن الاستغناء عن self؟

\n\n

هناك حالات لا يعمل فيها $this ببساطة، ويكون self هو الخيار الوحيد:

\n\n
    \n
  • الطرق الثابتة: داخل طريقة تم تعريفها كـ public static function، لا يوجد كائن، لذا $this غير متاح. فقط self.
  • \n
  • ثوابت الفئة: يتم الوصول إليها عبر self::CONSTANT (أو ClassName::CONSTANT).
  • \n
  • الخصائص الثابتة: self::$property.
  • \n
  • داخل المُنشئ أو المُدمّر: على الرغم من أن $this متاح هناك، إلا أنه من الأفضل استخدام self للعمليات الثابتة.

المدونات

توصيات الكتب