التوابع السحرية في PHP

التوابع السحرية PHP function magic هي التوابع التي تستخدم في الأصناف Classes و الكائنات Objects حيث تحجز PHP جميع الدوال التي تبدء ب __ (إشارتان سفليتان) كدوال سحرية

سنقوم بهذه المقالة بشرح أشهرهم، مع التنبيه على أنَّ الأمثلة خاصة باصدارات php8.0 وأعلى

التوابع __get() و __set() و __call()

__set()

يستخدم التابع لتخزين أو تمرير مفتاح وقيمة للكائن Object مثل: (سيتم وضع مثال بسيط في نهاية المقالة يحوي التوابع بمثال حقيقي):

$object = new Object();
$object->key = 'value'; // run function __set

__get()

يستخدم التابع لجلب قيمة من الكائن Object بعدما تم تخزينها باستعمال التابع السابق، أو من خلال خوارزمية بسيطة، مثال:

$object = new Object();
echo $object->key; // run function __get

__call()

يستخدم التابع لتنفيذ توبع غير موجودة بالأساس ! في الكائن object مما يجعلك تطفوا بأفاق كبيرة، مثلاً:

التابع __callStatic() يقوم بنفس العملية لكن يعامل كتابع static أي على مستوى الصنف class
$object = new Object();
echo $object->getKey(); // run function __call

الأن لنجمع الدوال السابقة بصنف واحد Class وننشأ كائن Object أيضاً:

سنقوم بإنشاء صنف نقوم بتمرير له بعض المعلومات، ونستطيع الإستفادة من هذه المعلومات من خلال إستدعائها بشكل أو مباشر أو إستدعاء التابع بإسم getName() بحيث نقوم بإستبدل “Name” بإسم القيمة التي أسندناها

<?php
error_reporting(E_ALL); // show all error
class test{
    /**
     * @var array $data storage data here
     */
    private array $data;
    public function __set(string $key,mixed $value) :void
    {
         // echo "you set \${$key}".PHP_EOL;
        $this->data[$key] = $value;
    }
    public function __get(string $key):mixed
    {
         // echo "you get \${$key}".PHP_EOL;
        return $this->data[$key] ?? null;
    }
    public function __call(string $function,array $arguments)
    {
         // echo "you call \$this->{$function}()".PHP_EOL;
        return $this->data[
        lcfirst(
            preg_replace('/^get(.*)/','$1',$function)
        )] ?? null;
    }
}
$data = new test;
$data->name = "yhya";
$data->twitter = "@SyrianYhya";
print_r([
   'name'   => $data->name,
   'twitter'=> $data->getTwitter()
]);

هذا المثال كان أحد التحديات التي أنشرها على قناتي على التلجرام

التوابع __sleep() و __wakeup()

__sleep()

يقوم بإرجاع قيمة من نوع Array بحيث يتم تحديد العناصر أو المتغيرات التي نحتاجها عند القيام بعملية سَلْسَلَة (serialization)

تعريف السَلْسَلَة

هي عملية تقوم على تحويل البيانات من أي نوع كان إلى قيمة من نوع string لتخزينها أو حفظها بأي مكان

تكمن الفائدة منها عند القيام بعملية فك سلسلة (عملية معاكسة للسلسة) سترجع البيانات بنفس النوع وهذا يعني إذا البيانات من نوع int ستعود القيمة لك بنوع int

هذه العملية مستخدمة في العديد من اطر العمل، مثل wordpress و laravel

مثال لعملية السلسة:

$data = 2024;
$exportData = serialize($data); // عملية السلسة
$result = unserialize($exportData); // فك سلسة
echo "{$result} type is:". gettype($result);

__wakeup()

يفيد في تغير البيانات من المتغيرات الخاصة بالكائن أو إجراء العمليات عليه الذي تم سلسلته وذلك بعد فك سلسته والأن سأرفقك بكود يشرح التابعين معاً:

<?php
class Test
{
    public function __construct(
        protected string $name
    ){}
    public function getName():string
    {
        return $this->name;
    }
    public function __sleep():array
    {
        return ['name'];
    }
    public function __wakeup():void
    {
        $this->name = "new name";
    }
}
$object = new Test('Yhya');
echo $object->getName().PHP_EOL; // Yhya
$data = serialize($object); // عملية السلسة
$result = unserialize($data); // عملة فك سلسة، ستؤدي لتنشيط تابع __wakeup()
echo $result->getName(); // new name

التوابع __toString() و __invoke() و ‎__construct()

‎__construct()

من أشهر هذه التوابع الذي تقوم بتمرير بعض الوسائط Arguments لكي يتم إسنادها في المتغيرات الخاصة بالصنف Object وفي هذا الخصوص أريد ذكر إختلفين جوهريين في اصدارات PHP 8 قبل وبعد

قبل PHP 8

class test
{
    public $firstName;
    public $lastName;
    public function __construct($firstName,$lastName)
    {
        $this->firstName = $firstName;
        $this->lastName = $lastName;
    }
}

بعد PHP 8

class test
{
    public function __construct(
        public string $firstName,
        public string $lastName
    ){}
}

أظن ان الفرق أصبح واضح وهو إمكانية إنشاء المتغيرات بداخله بحيث يتم إسنادها بشكل تلقائي عند الإستدعاء

__toString()

يرجع التابع قيمة نصية string حيث يقوم التابع بتحويل الكائن object لنص سواء من خلال إستدعائه بشكل مباشرة أو إستخدامه بتابع أخر يتطلب قيمة string (سيتوضح ذلك في المثال)

__invoke()

يأخذ التابع قيم عديدة (arguments) يتم إستدعائه عند معاملة الكائن Object كتابع Function ويقوم بتنفيذ التعليمات المضمنة

والأن سأعطي مثال عن التابعين السابقين:

<?php
class Test
{
    public function __construct(
        private string $name,
        private int $age
    ){}
    public function __toString():string
    {
        return "Hello {$this->name}, Your age is: {$this->age}";
    }
    public function __invoke(string $name):string
    {
        return $name === $this->name ? "name is true" : "name is false";
    }
}
$object = new Test('Yhya',18);
echo $object.PHP_EOL; // you can use $object->__toString()
echo "Welcome ".mb_substr($object,6).PHP_EOL;
echo $object('Syrian').PHP_EOL;

هذه أشهر التوابع السحرية (لم يتبقى سوا القليل وأظنها غير مهمة لكن لا تقلق سأقوم بشرحها في الأيام المقبلة على هذه التدوينة نفسها)

التوابع السحرية في PHP

PHP: Magic Methods – Manual

في حال ظننت أنّ هناك مشكلة فرجاءً تواصل معي عبر صفحة التواصل وفي حال لم يكن وأعجبت بالمقالة فخذ لك نظرة على المقالات الموجودة في موقع مدونة يحيى

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *

Scroll to Top