دعونا اليوم نتكلم عن (method chaining) شيء كثراً ما نجده باطر العمل والمكتبات البرمجية .

method chaining تجعل الكود اكثر تنظيما واسهل للقرأة كما انها تساعد المُبرمج على اختصار بعض الوقت والجهد .

لنفرض اننا قٌمنا بانشاء class لقاعدة البيانات طريقة التعامل معه كما يلي :

// انشاء object من ال class
$db = new Database;

// تحديد الجدول الذي نريد الاستعلام منه
$db->setTable("blogs");

// تحديد ما نُريد الاستعلام عنه
$db->setQuery("SELECT *");

// وضع حد اعلى من عدد النتائج
$db->setLimit(10);

// تحديد التباعد بين الصفوف
$db->setOffset(2);

// احضار نتيجة الاستعلام
var_dump($db->getResults());

يبدو الكود السابق جيد ولكن ما رأيك بتحسينه اكثر ؟

مثلاً لو كان كما يلي :

$db->setTable('blogs')->setQuery('SELECT *')->setLimit(10)->setOffset(2)->getResults();

وليكن اكثر قابلية للقرائة :

$db->setTable('blogs')
    ->setQuery('SELECT *')
    ->setLimit(10)
    ->setOffset(2)
    ->getResults();

ولكن بهذه الحالة , يعطني خطأ ولن يتم تنفيذ شيء !؟

ركز على الخطأ ! ماذا يقول ؟ نعم انه يقول باننا نحاول استدعاء دالة من null !

حسناً دعونا نقوم ببناء ال class !:

class Database
{
    private 
            $table,
            $query,
            $limit,
            $offset;


    public function setTable($table)
    {
        $this->table = $table;
    }

    public function setQuery($query)
    {
        $this->query = $query;
    }

    public function setLimit($limit)
    {
        $this->limit = $limit;
    }

    public function setOffset($offset)
    {
        $this->offset = $offset;
    }

    public function getResults()
    {
        $selectQuery = 
            "$this->query FROM $this->table LIMIT $this->limit OFFSET $this->offset";

        // لن نقوم بعملية الاتصال بالبيانات واحضار بيانات حقيقية
        // لذا سنقوم باعادة بيانات وهمية

        return [
            0 => [
                'id' => 1,
                'title' => 'the title',
                'body' => "Lorem ipsum dolor sit amet."
            ],
            1 => [
                'id' => 2,
                'title' => 'the title',
                'body' => "Lorem ipsum dolor sit amet."
            ],

            2 => [
                'id' => 3,
                'title' => 'the title',
                'body' => "Lorem ipsum dolor sit amet."
            ],

            3 => [
                'id' => 4,
                'title' => 'the title',
                'body' => "Lorem ipsum dolor sit amet."
            ],
        ];
    }
}

ولكن حتى الأن سيعمل الكود بالمثال الاول اما بالمثال الثاني فلن يعمل وسيعطني الخطأ السايق ذكره !

حسناً ما الحل ؟؟

سبق وقلنا بان الخطأ مفاده باننا نحاول استدعاء دالة من null < وهذا يعود على اننا نريد استدعاء الدالة setQuery من الدالة setTable والتي تعيد null !

الحل هنا هو ان نجعل الدالة setTable تعيد كائن من نفس ال class (كيف ؟؟) هكذا بكل بساطة

نعدل على الدالة setTable

public function setTable($table)
{
    $this->table = $table;

    return $this;
}

حسناً ولكن بقي يعطي نفس الخطأ مع تغيير اسم الدالة ! الحل هو جعل جميع الدوال التي نريد الاستدعاء منها تعيد $this

public function setTable($table)
{
    $this->table = $table;

    return $this;
}

public function setQuery($query)
{
    $this->query = $query;

    return $this;
}

public function setLimit($limit)
{
    $this->limit = $limit;

    return $this;
}

public function setOffset($offset)
{
    $this->offset = $offset;

    return $this;
}

public function getResults()
{
    $selectQuery = 
        "$this->query FROM $this->table LIMIT $this->limit OFFSET $this->offset";

    // لن نقوم بعملية الاتصال بالبيانات واحضار بيانات حقيقية
    // لذا سنقوم باعادة بيانات وهمية

    return [
        0 => [
            'id' => 1,
            'title' => 'the title',
            'body' => "Lorem ipsum dolor sit amet."
        ],
        1 => [
            'id' => 2,
            'title' => 'the title',
            'body' => "Lorem ipsum dolor sit amet."
        ],

        2 => [
            'id' => 3,
            'title' => 'the title',
            'body' => "Lorem ipsum dolor sit amet."
        ],

        3 => [
            'id' => 4,
            'title' => 'the title',
            'body' => "Lorem ipsum dolor sit amet."
        ],
    ];
}

والان كل شيء يعمل وبدون اي مشاكل :) .

ماذا نلاحظ ؟

نلاحظ ان الـ setters كونها لا تُرجع اي قيمة يمكننا ان نجعلها تعيد كائن من نفس ال class لنستدعي دالة اخرى من خلالها .

الديك اي سؤال ؟ لا تخجل من وضعه في التعليقات!