Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

__get, __set, __isset, __unset

جزء من قسم Object Oriented Programming في رحلة PHP على Coddy — الدرس 46 من 91.

يوفر PHP أربع طرق سحرية (magic methods) تعترض الوصول إلى الخصائص: __get()، و __set()، و __isset()، و __unset(). يتم استدعاء هذه الطرق عندما تحاول الوصول إلى خصائص غير موجودة أو غير قابلة للوصول.

يتم استدعاء الأسلوب __get() عند قراءة خاصية غير قابلة للوصول، بينما يتعامل __set() مع الكتابة إلى واحدة. يتيح لك ذلك إنشاء خصائص ديناميكية أو إضافة منطق عند الوصول إلى الخصائص:

<?php
class DynamicObject {
    private array $data = [];
    
    public function __get(string $name): mixed {
        return $this->data[$name] ?? null;
    }
    
    public function __set(string $name, mixed $value): void {
        $this->data[$name] = $value;
    }
}

$obj = new DynamicObject();
$obj->title = "Hello";
$obj->count = 42;
echo $obj->title . " - " . $obj->count;

المخرجات:

Hello - 42

يتم استدعاء الطريقة __isset() بواسطة isset() أو empty()، وتستجيب __unset() للدالة unset():

<?php
class DynamicObject {
    private array $data = [];
    
    public function __set(string $name, mixed $value): void {
        $this->data[$name] = $value;
    }
    
    public function __isset(string $name): bool {
        return isset($this->data[$name]);
    }
    
    public function __unset(string $name): void {
        unset($this->data[$name]);
    }
}

$obj = new DynamicObject();
$obj->name = "Test";
echo isset($obj->name) ? "exists" : "missing";

المخرجات:

exists

تُستخدم هذه الطرق بشكل شائع لإنشاء حاويات بيانات مرنة، أو تنفيذ التحميل الكسول (lazy loading)، أو بناء كائنات تتصرف مثل المصفوفات مع الحفاظ على الهيكل كائني التوجه (object-oriented structure).

challenge icon

التحدي

سهل

لنقم ببناء مدير إعدادات مرن يقوم بتخزين الإعدادات ديناميكيًا باستخدام الطرق السحرية (magic methods). سيقوم صنفك (class) باعتراض الوصول إلى الخصائص لإدارة قيم الإعدادات، والتحقق من وجود الإعدادات، وإزالتها عند الحاجة — كل ذلك دون تحديد كل خاصية بشكل صريح.

ستقوم بتنظيم الكود الخاص بك عبر ملفين:

  • Config.php — أنشئ صنف Config يستخدم مصفوفة خاصة (private array) لتخزين قيم الإعدادات داخليًا. قم بتنفيذ جميع الطرق السحرية الأربعة للخصائص:
    • __get($name) — يعيد القيمة للمفتاح المعطى، أو "undefined" إذا كان المفتاح غير موجود
    • __set($name, $value) — يخزن القيمة تحت المفتاح المعطى
    • __isset($name) — يعيد ما إذا كان المفتاح موجودًا في الإعدادات
    • __unset($name) — يزيل المفتاح من الإعدادات
    أضف أيضًا دالة count() تعيد عدد الإعدادات المخزنة.
  • main.php — قم بتضمين ملف Config. ستتلقى ثلاثة مدخلات: اسم الإعداد، قيمة الإعداد، واسم إعداد ثانٍ. أنشئ كائنًا (instance) من Config وقم بإجراء العمليات التالية:
    • قم بتعيين الإعداد الأول إلى القيمة المعطاة
    • اطبع ما إذا كان الإعداد الأول موجودًا باستخدام isset() — المخرج "exists" أو "missing"
    • اطبع قيمة الإعداد الأول
    • اطبع العدد الحالي للإعدادات
    • استخدم unset() لإزالة الإعداد الأول
    • اطبع ما إذا كان الإعداد الأول موجودًا الآن — المخرج "exists" أو "missing"
    • اطبع قيمة الإعداد الثاني (الذي لم يتم تعيينه مطلقًا)

يجب أن يكون كل مخرج في سطر مستقل. تتيح لك الطرق السحرية التفاعل مع كائن Config الخاص بك باستخدام صيغة الخصائص الطبيعية مثل $config->theme = "dark" و isset($config->theme)، على الرغم من عدم تعريف أي خصائص فعلية.

ورقة مرجعية

يوفر PHP أربع طرق سحرية (magic methods) لاعتراض الوصول إلى الخصائص:

  • __get(string $name): mixed — يتم استدعاؤها عند قراءة خاصية لا يمكن الوصول إليها
  • __set(string $name, mixed $value): void — يتم استدعاؤها عند الكتابة في خاصية لا يمكن الوصول إليها
  • __isset(string $name): bool — يتم تفعيلها بواسطة isset() أو empty()
  • __unset(string $name): void — يتم تفعيلها بواسطة unset()

مثال على __get() و __set():

<?php
class DynamicObject {
    private array $data = [];
    
    public function __get(string $name): mixed {
        return $this->data[$name] ?? null;
    }
    
    public function __set(string $name, mixed $value): void {
        $this->data[$name] = $value;
    }
}

$obj = new DynamicObject();
$obj->title = "Hello";
echo $obj->title; // Hello

مثال على __isset() و __unset():

<?php
class DynamicObject {
    private array $data = [];
    
    public function __set(string $name, mixed $value): void {
        $this->data[$name] = $value;
    }
    
    public function __isset(string $name): bool {
        return isset($this->data[$name]);
    }
    
    public function __unset(string $name): void {
        unset($this->data[$name]);
    }
}

$obj = new DynamicObject();
$obj->name = "Test";
echo isset($obj->name) ? "exists" : "missing"; // exists

تسمح هذه الطرق باستخدام الخصائص الديناميكية، والتحميل الكسول (lazy loading)، وحاويات البيانات المرنة مع الحفاظ على بنية البرمجة كائنية التوجه.

جرّب بنفسك

<?php

require_once 'Config.php';

// قراءة المدخلات
$settingName1 = trim(fgets(STDIN));
$settingValue = trim(fgets(STDIN));
$settingName2 = trim(fgets(STDIN));

// TODO: إنشاء مثيل (instance) من Config

// TODO: تعيين الإعداد الأول إلى القيمة المعطاة

// TODO: طباعة ما إذا كان الإعداد الأول موجوداً أم لا ("exists" أو "missing")

// TODO: طباعة قيمة الإعداد الأول

// TODO: طباعة العدد الحالي للإعدادات

// TODO: استخدام unset() لإزالة الإعداد الأول

// TODO: طباعة ما إذا كان الإعداد الأول موجوداً الآن ("exists" أو "missing")

// TODO: طباعة قيمة الإعداد الثاني (الذي لم يتم تعيينه مطلقاً)

?>
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس Object Oriented Programming