[php5] بناء نظام MVC بسيط [3]

مدرج تحت قسم: دروس
17 سبتمبر 2007

بعد أن بدأنا الحديث عن MVC في المقال السابق سنكمل الحديث في هذا المقال في الجزء الثالث

ثالثاً: النموذج The Model

[M] أو Model هو جزء من MVC مسئول عن الاستعلام عن البيانات المراد عرضها من قاعدة البيانات أو من اى مصدر آخر ثم يقوم بتقديمها للمتحكم Controller، ويجب علينا ان نحصل على النموذج المناسب للطلب المقدم من المستخدم ولكن هنا سنقوم بطمس الفرق بين النموذج والمتحكم ، حيث يستخدم المتحكم مكتبة اتصال بقاعدة بيانات للاستعلام مباشرة من قاعدة البيانات بدلا من العديد من النماذج المختلفة فلذلك لن نتضمن النماذج في نظامنا بشكل رسمي واذا استطعت ان تفهم فكرة عمل المتحكم عند شرحة في الجزء الرابع سيمكنك ( إذا احببت ) القيام بإضافة النماذج بنفس الطريقة.

سنقوم هنا بإضافة كود الاتصال بقاعدة البيانات لصفحتنا الرئيسية index.php داخل المجلد MVC، يمكنك استخدام مكتبات الاتصال بقواعد البيانات المختلفة ولكن PHP5 ياتي معها مكتبة اتصال بقواعد البيانات قوية وهي PDO وسأقوم باستخدامها هنا نظرا لوجود اتجاه رسمي من مطوري PHP لازالة اى مكتبات اتصال بقواعد البيانات غير PDO مثل OCI8 and MySQLi من الوضع الافتراضي واحالتهم الي PECL في PHP6 واعتماد PDO بشكل رسمي كمكتبة الاتصال بقواعد البيانات في PHP6.

قوم بإضافة هذا الكود الي index.php إذا كنت ستستخدم PDO واذا لم تريد استخدامها فقم بإضافة. كود الاتصال الخاص بالمكتبة التي تنوي استخدامها MySQLi مثلاً.

$db = new PDO('mysql:host=localhost;dbname=demo', '[user]', '[password]');
$registry->set ('db', $db);

فى السطر الأول قمنا بعمل مقبض اتصال بقاعدة بيانات من نوع MySql باستخدام pdo. قم بتغيير demo الي اسم القاعدة و user الي اسم المستخدم و password الي كلمة السر.

ثم في السطر الثاني قمنا بتخزين هذا المقبض في كائن التسجيل حتي نجعله متغير عام global و يتاح لنا استخدامه في اى صفحة آخري من السكربت عن طريقة استخراجه من كائن التسجيل كما سبق شرحه.

فبهذه الإضافة البسيطة نكون انهينا جزء النموذج الذي اتفقنا عليه بأن لا يكون نماذج مختلفة في درسنا هذا. وسنبدأ بإضافة المتحكم Controller وإضافة المتحكم هذه تعني أننا بحاجة لكائن المسارات المسئول عن تحميل المتحكم controller المطلوب من خلال المستخدم عن طريق الرابط.

كائن المسار Router

سيقوم هذا الكائن بتحليل الطلب القادم من المستخدم ثم تحميل المتحكم الصحيح للبدء بعرض المطلوب عرضه ، الخطوة الأولي هي عمل الهيكل الاساسي لكائن المسار وإضافةه في ملف router.php بمجلد classes السابق انشائه وموجود به registry.php.

Class Router {
        private $registry;
        private $path;

        function __construct($registry) {
                $this->registry = $registry;
        }
}

قمنا هنا ببناء هيكل كائن المسار وتحديد 3 خواص.

  1. خاصية التسجيل وستحتوي على كائن التسجيل المسبق إنشاؤه
  2. خاصية المسار وستحتوي على المسار الكامل للمتحكم ثم نقوم ببناء
  3. المشيد الذي ياخذ كائن التسجيل كمعطي ثم يقوم بتعيينه لخاصية التسجيل
  4. قم الآن بإضافة الكود الاتي الي صفحة index.php للقيام بتحميل كائن المسار.

    $router= new Router($registry);
    $registry['router'] =  $router ;
    

    فى السطر الأول قمنا بعمل نسخة من كائن المسار في متغير router. ثم قمنا بتسجيل قيمة المتغير router بالمفتاح router في كائن التسجيل ليكون المتغير router عام ويمكن استخدامه بجميع الصفحات وهو يحوي بداخله نسخة من كائن المسار.

    لنقوم بإضافة الوسائل الاساسية في كائن المسار ، أول وسيلة هي وسيلة setPath()، والتي تستخدم لتحديد الدليل ( المجلد ) الذي سيحوي جميع عناصر التحكم controllers وسنقوم الآن بإضافةها الي ملف router.php داخل الكائن router من الكود الاتي.

     function setPath($path)
    {
    $path = trim($path, '/\\');
            $path .= DS;
    
    if (is_dir($path) == false) {
            $perror= 'Invalid controller path '.$path;
            die($perror);
            }
    
            $this->path = $path;
    }
    

    لنرجع الآن إلى ملف index.php ونقوم بإضافة السطر التالي لتحديد مسار مجلد عناصر التحكم controllers.

    $router->setPath(site_path.'controllers');
    

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

    الجزئية الأولي من هذه الوسيلة كالاتي.

    function loading(){
            $this->getController($file,$controller,$action);
    

    كما نري فان وسيلة التحميل loading() تستخدم وسيلة آخري وهي getController() للحصول على اسم عنصر التحكم واذا تم طلب تنفيذ دالة داخله والكود الاتي هو وسيلة getController().

    private function getController(&$file, &$controller, &$action) {
            $route = (empty($_GET['route'])) ? '' : $_GET['route'];
            if (empty($route)) { $route = 'index'; }
    
            $route = trim($route, '/\\');
            $parts = explode('/', $route);
    
            $cmd_path = $this->path;
            foreach ($parts as $part) {
                   $fullpath = $cmd_path . $part;
    
                    if (is_dir($fullpath)) {
                            $cmd_path .= $part . DS;
                            array_shift($parts);
                            continue;
                    }
    
                    if (is_file($fullpath . '.php')) {
                            $controller = $part;
                            array_shift($parts);
                            break;
                    }
            }
            if (empty($controller)) { $controller = 'index'; };
    
            $action = array_shift($parts);
            if (empty($action)) { $action = 'index'; }
            $file = $cmd_path . $controller . '.php';
    }
    

    فى هذه الوسيلة تاخذ أولاً قيمة المتغير $route ثم تقوم بتقسيمه الي اجزاء منفصلة باستخدام دالة explode() فاذا كان الطلب ( links/view ) فستقوم بتقسيمه الي مصفوفة array(’links’,'view’).

    ثم نقوم باستخدام حلقة تكرار foreach لاستخراج القيم من المصفوفة كل على حدي ثم التاكد من كونه مجلد، فاذا كان مجلد نقوم بإضافةه الي مسار الملف ثم ننتقل للجزء التالي من المصفوفة مع حذف الجزء الذي يمثل مجلد من المصفوفة باستخدام array_shift وهكذا ، هذا يتيح لنا استخدام مجلدات فرعية داخل المجلد الرئيسي لعناصر التحكم controllers.

    واذا كان الجزء التالي ليس مجلد ولكنه ملف نقوم بتعيين هذا الجزء لمتغير $controller ونحذف عنصر الملف من المصفوفة ثم نخرج من الحلقة لحصولنا على ملف عنصر التحكم المنشود ، بعد الحلقة نتاكد من ايجاد عنصر التحكم فاذا لم يتم ايجادة نقم باستخدام الافتراضي وتعيين القيمة الافتراضية ونطلق عليها هنا index الي $controller.

    ثم نقوم بالحصول على الوسيلة المطلوبة الموجودة داخل عنصر التحكم ، فعنصر التحكم هو كائن يتكون من مجموعة وسائل مختلفة والمتغير action يشير الي الوسيلة المطلوبة من خلال المستخدم واذا لم نجد وسيلة تم تحديدها فنقوم بارجاع الوسيلة الافتراضية index وفى النهاية نقوم بتجميع المسار الكامل لملف عنصر التحكم ( المسار و اسم عنصر التحكم و الامتداد ) ، الآن الطلب تم تحليله داخل الوسيلة الحاملة له وهي loading() فتقوم بتحميل عنصر التحكم و تنفيذ الوسيلة المطلوبة ، الكود الاتي يمثل وسيلة loading() كاملة بملف router.php.

    function loading() {
            $this->getController($file, $controller, $action);
    
      if (is_readable($file) == false) {
                    die ('404 File Not Found');
            }
    
            include ($file);
            $class = 'Controller_' . $controller;
            $controller = new $class($this->registry);
    
            if (is_callable(array($controller, $action)) == false) {
                    die ('404 Action Not Found');
            }
            $controller->$action();
    }
    

    فى السطر الأول نقوم باستدعاء وسيلة الحصول على عنصر التحكم وتم شرحها مسبقا، ثم نتاكد من ملف عنصر التحكم موجود بالفعل فاذا كان موجود نقوم بتضمينه include واذا لم يكن نخرج رسالة خطأ ثم نقوم بتعريف الكلاس بسابقة Controller ثم اسم الملف ثم نقوم بعمل نسخة من الكلاس لاستخدامها في آخراج الوسيلة المطلوبة وبعد ذلك نقوم بالتاكد من ان الوسيلة المطلوبة هي دالة يمكن تفيذها داخل كائن عن طريق إدخالهم على شكل مصفوفة ثم تنفيذها واذا لم تكن نخرج رسالة خطا.

    والآن اكتملت وسيلة التشغيل الاساسية loading() سنقوم بإضافة السطر الاتي الي نهاية index.php.

    $router->loading ();
    

    سننتقل الآن الي عناصر التحكم Controllers في الجزء الرابع.

عن الكاتب

Hawy_PHP مبرمج ومطور مواقع ، طالب بمدرسة تكنولوجيا المعلومات ، مدمن برمجة :)

  • Share/Bookmark

التعليقات (3) على ”[php5] بناء نظام MVC بسيط [3]“

  1. لك الف شكر اخي
    و كل عام و انت بخير
    تحياتي

  2. جزاك الله كل خير
    يارب تكون استفدت منه

  3. مجهود مميز
    جزاك الله خسرا

أضف تعليقك




يمكنك استخدام الوسوم التالية في التعليق: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>


* حقول مطلوبة