[php5] بناء نظام MVC بسيط [1,2]
الكاتب: Hawy_PHP | 15 سبتمبر 2007
كيف تبني نظام (Model–Controller–View) المعروف ب MVC و (المستخدم في جميع اطارات العمل FrameWorks)..
للمزيد عن مفهوم ال MVC وجدت تدوينة للأستاذ عبدالله المهيري - سردال تتحدث عن مفهوم ال MVC و مثال له في ال PHP وآخر في ال Ruby
[نظرة على أطر العمل MVC ]
يتم ذلك باستخدام PHP5 و أحد خصائص SPL) Standard PHP Library): وهي مكتبة تحتوي على مجموعة من الواجهات و الكائنات لحل بعض المشاكل القياسية
تحتاج لتطبيق هذا الدرس:
- توفر نسخة PHP5 و مكتبة SPl المضافة افتراضيا في نسخة PHP 5 (أنصحك باستخدام Xampp 1.6.3a - يحتوي على نسخة PHP 5.2.3)
وستجد هنا درس تنصيب xampp للأخ الفاضل أشرف السمهوري - وان يكون لديك خلفية ولو بسيطة عن البرمجة الكائنية والوراثة
فى هذا الدرس ستتعلم أساسيات أي نظام MVC (أكثر نمط تصميم شيوعاً لتطبيقات الويب الكبيرة)، وكيف تبني أساس هذا النظام من الصفر وكيف تتعامل معه.
أولاًً: المقدمة و نقطة أساس النظام
لنبدأ بتوضيح أحد أساسيات هذا النظام وهي صفحة واحدة تعالجنا (كلنا) >> ( همّا مين {كلنا} دول :D )
أقول لك أنا هذه كل العمليات التي سيتم معالجتها لإظهار المحتوي الذي تريده؛ فبدلاً من أن تضع هذا السطر في كل صفحة
-
include ("Global.php");
-
// بقية محتويات الكود الخاص بهذا الملف
سيكون عندنا صفحة تقوم بمعالجة كل العمليات لعرض المطلوب - أي أننا لن نكون بحاجة لإدراج ملف global.php مثلاًً في كل ملف جديد نقوم بعمله.
سنقوم الآن ببداية التطبيق:
- قم بعمل مجلد فارغ وليكن MVC ، ثم أنشئ ملفاً فارغاً بإسم index.php
الآن سنقوم بعمل بعض المهام التي سنحتاجها في بداية معالجة العمليات:
- قم بعمل مجلد includes وأنشئ ملفاً بإسم startup.php بداخله
- قم بإضافة السطر التالي لملف الـ index.php
-
include_once("includes/startup.php");
ثانياًً: مهام البدء و كائن التسجيل
الجزئية الأولي : مهام البدء :
يستخدم ملف البداية في القيام ببعض مهام بداية التنفيذ العامة، مثل تعريف الثوابت، و تحديد مستوي الأخطاء المراد تفعيلها، والحصول على المسار الخاص بالإطار.
سيكون الجزء الأول من ملف البداية startup.php بهذا الشكل:
-
-
$ver_error=' Sorry
-
<h1> PHP 5 Only !!</h1>
-
' ;
-
-
-
-
فى السطر الأول قمنا بإعداد مستوي الاخطاء لاظهار جميع الاخطاء
لمزيد عن الاخطاء درس الاخطاء في لغة PHP للاخ الفاضل أشرف السمهوري
ثم في السطر الثاني قمنا بتنسيق رسالة تحذيرية لعرضها في حالة عدم استخدام PHP5
نظرا لأن النظام يعتمد بشكل اساسي على بعض ادوات SPL المتوفرة في PHP5 فقط
فى السطر الثاالث نقوم بالتاكد من نسخة ال PHP إذا كانت أقل من 5 نقوم بايقاف التنفيذ
مع اظهار الرسالة السابق تنسيقها في السطر الثاني
فى السطر الرابع نقوم بعمل ثابت DS يحتوي على فاصل الادلة DIRECTORY_SEPARATOR
وهو الباك سلاش [ \ ] لاختصار كتابته ليس اكثر
فى السطر الخامس نقوم بالحصول على مسار الموقع الحقيقي بهذه الطريقة
نقوم في البداية بمعرفة اسم المجلدdirname للملف الحالى __FILE__ وهو في حالتنا هنا startup.php
وسيكون اسم المجلد هو includes ثم نضيف \ ثم ال .. ليخرجونا للمجلد الاعلي من includes
وهو المجلد الرئيسي لنا MVC كما ذكرنا سابقا عند إنشاء index.php
فى السطر السادس نقوم بعمل ثابت site_path يحتوي على قيمة المتغير المحتوي على مسار المجلد الرئيسي في السطر الخامس $sitepath ليصبح عندنا الثابت site_path به مسار المجلد الرئيسي
كل ما في هذا الملف سيتم تنفيذه في بداية اى تنفيذ لأي ملف في النظام .
الجزئية الثانية : كائن التسجيل :
الجزء القادم هو احتياجنا لكائن تسجيل يقوم باحتواء كل البيانات العامة على النظام باكمله
هذا الكائن سيضمن داخل كل الكائنات المستقلة الاخري في النظام ويستخدم لنقل البيانات العامة في مختلف انحاء النظام بدون الاحتياج لاستخدام المتغير المسبق التعريف $GLOBALS
سنقوم بإنشاء الكائن ( الكلاس ) هذا في ملف خارجي وسنقوم باستدعائه ببساطة باستخدام include()
ولكن هيا نستخدم واحدة من روائع PHP5 الجديدة وهي الدالة [ __autoload() ]
هذه الدالة الساحرة تستخدم لتحميل الكائنات ( الكلاسات ) ، عندما تصادف PHP كائن غير موجود
فتقوم أولاًً باستدعاء الدالة __autoload() ، ثم تقوم بالاعلان عن خطأ إذا لم يكن موجودا .
لنقم بإضافة الكود الاتي إلى ملف startup.php
-
function __autoload($class_name)
-
{
-
-
$file = site_path . 'classes' . DS . $filename;
-
-
{
-
return false;
-
}
-
-
include ($file);
-
}
تاخذ الدالة اسم الكلاس كمعطي لها ، ثم تتاكد من وجود ملف له نفس الاسم بداخل مجلد الكائنات الذي نقوم بعمله وتسميته مثلاً classes . إذا لم تجد الملف الدالة سوف تقوم بايقاف التنفيذ واظهار خطأ قاتل fatal error يتم ايضاح فيه ان االكلاس ( اسم الكلاس ) غير موجود ،
واذا وجدت الملف ستقوم الدالة بتضمينه بواسطة include()
إنشاء كائن التسجيل
كائن التسجيل كما قلنا سابقا فهو يضمن داخل كل الكائنات المستقلة الاخري ويقوم بنقل البيانات العامة في مختلف انحاء النظام ، وهو كائن (كلاس) بسيط جدا ، ولا يحتاج أكثر من ثلاثة أساليب (نهج) methods.
أولاًً نقوم بإنشاء مجلد واسمه [ classes ] ثم نقوم بإنشاء ملف جديد ونسميه [ regisrty.php ]
ونضع الكود الاتي بداخله
-
class Registry {
-
}
فى هذا السطر قمنا بإنشاء الكائن ووضع خاصية vars على شكل مصفوفة وهي التي ستحوي البيانات التي سنقوم بتخزينها من خلال الكائن .
نحن الآن قمنا بعمل هيكل لكائن التسجيل ( Registry Class ) ، و كل ما نريد فعله هو إضافة بعض الأساليب ( النهج ) ، جميع كائنات التسجيل تحتاج إلى أسلوب تخزين set() لتخزين البيانات ،
وأسلوب الإستخراجget() للحصول على البيانات المخزنة ، ويمكننا أيضا إضافة أسلوب الحذف remove() ليقوم بحذف بعض البيانات المخزنة بالكائن ، سنضيف الكود الاتي الخاص بهذه الأساليب داخل الكائن:
-
function set($key, $var) {
-
$error='Unable to set var <font color="red"><strong> '.$key.'</strong></font> Already Set !!';
-
}
-
$this->vars[$key] = $var;
-
return true;
-
}
-
function get($key) {
-
return null;
-
}
-
return $this->vars[$key];
-
}
-
function remove($var) {
-
}
الأساليب بسيطة جدا كل إلى بتقوم بيه ( تخزن ، تستخرج و تحذف ) البيانات من خاصية$var ، في أسلوب التخزين set() نقوم ايضا بالتاكد إذا كان مفتاح البيانات المدخلة موجود من قبل ام لا ، فاذا كان موجود نقوم بالخروج من البرنامج واظهار خطأ وهذا يحمي من الكتابة على البيانات الموجودة من قبل [ Overwriting ] .
نحن الآن بنينا كائن تسجيل كامل ولكن سنقوم باستخدام احد واجهات (وصلات) SPL وهي[ ArrayAccess]
وتعمل على الوصول للكائن بطريقة المصفوفات ، لاحظ الكود الاتي ولا تضيفه [ يعتمد على الكائن السابق] :
-
$registry = new Registry;
-
$registry-vset ( 'site' , 'almashroo.com' ) ;
-
-
$registry->get ('site');
-
-
$registry['site'];
- في السطر الأول نقوم بتعريف نسخة من كائن التسجيل
- في السطر الثاني نقوم بإدخال مفتاح site وقيمته almashroo.com
- في السطر الثالث نقوم بالحصول على قيمة المفتاح site باستخدام أسلوب الاستخراج get()
- أما في السطر الرابع فهو المقصود وهو نفس عمل السطر الثالث ( الحصول على قيمة المفتاح site ) ولكن باستخدام ال ArrayAccess فهي تتعامل مع $registry كانه مصفوفة في حين أنه كائن، و ال ArrayAccess لا تمتلك مميزات حقيقية، هي فقط تختصر الكتابة بدلاً من أنك تستخدم ->get()..
لاستخدام ال ArrayAccess يجب علينا تغيير السطر الخاص بتعريف الكلاس وهو:
-
class Registry {
ليصبح
-
Class Registry Implements ArrayAccess {
الكلمة المفتاحية [ Implements ] تستخدم لتفيذ واجهة ( وصلة ) interface مثل ال ArrayAccess بتنفيذ ArrayAccess يجب إضافة اربع أساليب جديدة ثابتة للكائن معرفة مسبقا من خلال SPL
قم باضافتهم اسفل الثلاث أساليب السابق ذكرهم
هذه الأساليب تشرح نفسها:
- فالأولى تقوم بالتحقق من وجود المتغير
- والثانية تقوم باستخراج المتغير
- والثالثة تقوم بإدخال المتغير وقيمته
- والرابعة تقوم بالحذف
وللمزيد عنهم:
بعد أن قمنا باستكمال كائن التسجيل وإضافة واجهة ArrayAccess، فإن طريقة إدخال البيانات واستخراجها أصبحت بالشكل التالي
- السطر الأول: إدخال البيانات بالطريقة العادية
- السطر الثاني: إدخال البيانات باستخدام Array Access
- السطر الثالث: استخراج البيانات بالطريقة العادية
- السطر الرابع: استخراج البيانات باستخدام Array Access
يبقي الآن إضافة هذا السطر في نهاية ملف startup.php السالف ذكره ( بعد دالة autoload )
-
$registry = new Registry;
انتهينا من كائن التسجيل واذا حاولت تجربة النظام فسيعمل بدون اخطاء ( ولكن لن يعرض شئ ) :D
يتبع بالجزء الثالث :D