1.4. Приступаем к написанию MVC-фреймворка
Мы уже достаточно расписали, что должно быть у нас в фреймворке, пришло время реализовать наш фреймворк. Для начала Вам нужен веб-сервер. Вы можете попробовать денвер, но возможно вам придется обновить PHP.
Скачать денвер с PHP 5.5.20 вы можете с этой страницы:
https://drupalbook.org/ru/drupal/denwer-obnovlenie-php
или с github'a
https://github.com/levmyshkin/denwer-php-5.5.20
Работа нашего фреймворка будет начинаться с файла index.php, который возвращает экземпляры из реестра, вызывает нужный контроллер и передает ему результаты реестра, контроллер в свою очередь может вызывать модели которые ему необходимы.
Реализация паттернов
Существует несколько различных путей реализовать паттерны, которые мы обсуждали. Мы выберем один из возможных вариантов, в будущем Вы можете поменять реализацию какого-нибудь из паттернов.
Давайте начнем, в одном из прошлых статей мы разобрали структуру нашего фреймворка, так что нам нужно будет создать папки исходя из этой структуры.
Теперь создайте файл Registry/registry.class.php. В этом файле мы напишем класс нашего реестра.
<?php /** * Объект реестра * Реализует паттерн Реестра и Единичный класс * */ class Registry { /** * Массив наших объектов * @access private */ private static $objects = array(); /** * Массив наших настроек * @access private */ private static $settings = array(); /** * Человекочитаемое название нашего фреймворка * @access private */ private static $frameworkName = 'Framework version 0.1'; /** * Экземпляр нашего реестра * @access private */ private static $instance; /** * Конструктор для нашего реестра * @access private */ private function __construct() { } /** * метод единичного класса для доступа к объекту * @access public * @return */ public static function singleton() { if( !isset( self::$instance ) ) { $obj = __CLASS__; self::$instance = new $obj; } return self::$instance; } /** * предотвращение копирования нашего объекта: проблем с E_USER_ERROR если это произошло */ public function __clone() { trigger_error( 'Cloning the registry is not permitted', E_USER_ERROR ); } /** * хранит объект в нашем реестре * @param String $object the name of the object * @param String $key the key for the array * @return void */ public function storeObject( $object, $key ) { require_once('objects/' . $object . '.class.php'); self::$objects[ $key ] = new $object( self::$instance ); } /** * получение объекта из нашего реестра * @param String $key the array key * @return object */ public function getObject( $key ) { if( is_object ( self::$objects[ $key ] ) ) { return self::$objects[ $key ]; } } /** * Хранит настройки нашего реестра * @param String $data * @param String $key the key for the array * @return void */ public function storeSetting( $data, $key ) { self::$settings[ $key ] = $data; } /** * Получение настроек нашего реестра * @param String $key the key in the array * @return void */ public function getSetting( $key ) { return self::$settings[ $key ]; } /** * Получение имени фреймворка * @return String */ public function getFrameworkName() { return self::$frameworkName; } } ?>
Так как же работает наш Реестр и как он хранит наши объекты?
- Объекты хранятся в виде массива
- Когда новый объект добавлен в реестр, файл класса также добавляется, создается экземпляр объекта и добавляется в массив
- Объект возвращаются с помощью передачи ключа объекта методу getObject
Как предотвращается создание другой копии объекта реестра?
- Конструктор является private, что позволяет предотвратить создание объектра напрямую
- Клонирование объекта вызовет ошибку
- Если вы хотите получить доступ к объекту реестра из нашего Фреймворка, и это невозможно из того файла, который сейчас отрабатывает, вы можете использовать статический метод singleton (Registry::singleton()) для получения экземляра Реестра.
Теперь когда у нас есть Реестр, давайте напишем index.php, чтобы вызывать работу фреймворка и обращаться к Реестру.
Index.php
Index.php - это стартовая точка работы нашего фреймворка.
Далее мы еще добавим возможность создавать ЧПУ, с помощью файла .htaccess. А пока давайте разберем код index.php:
<?php /** * Framework * Framework loader - acts as a single point of access to the Framework * */ // стартуем сессию session_start(); // задаем некоторые константы // Задаем корень фреймворка, чтобы легко получать его в любом скрипте define( "APP_PATH", dirname( __FILE__ ) ."/" ); // Мы будем использовать это, чтобы избежать вызов скриптов не из нашего фреймворка define( "FW", true ); /** * Магическая функция автозагрузки * позволяет вызвать необходимый -controller- когда он нужен * @param String the name of the class */ function __autoload( $class_name ) { require_once('Controllers/' . $class_name . '/' . $class_name . '.php' ); } // подключаем наш реестр require_once('Registry/registry.class.php'); $registry = Registry::singleton(); // выводим имя фреймворка, чтобы проверить, что все работает print $registry->getFrameworkName(); exit(); ?>
Если все правильно, то должно быть выведено сообщение с именем нашего фреймворка:
Framework version 0.1
Давайте разберемся как работает наш index.php на данный момент:
- Вызывается сессия, чтобы мы могли записывать данные и получать их в любом месте фреймворка.
- Мы определяем корневую папку нашего фреймворка, это позволит нам нормально работать не из корня сайта, а из папки.
- Подгружаем контроллеры с помощью автозагрузки
- Подключаем класс Реестра
- и выводим название нашего фреймворка.