دعونا اليوم نتكلم عن (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 لنستدعي دالة اخرى من خلالها .
الديك اي سؤال ؟ لا تخجل من وضعه في التعليقات!
التعليقات