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 на данный момент:
- Вызывается сессия, чтобы мы могли записывать данные и получать их в любом месте фреймворка.
- Мы определяем корневую папку нашего фреймворка, это позволит нам нормально работать не из корня сайта, а из папки.
- Подгружаем контроллеры с помощью автозагрузки
- Подключаем класс Реестра
- и выводим название нашего фреймворка.