Простая MVC модель.
Статью писал для своего сайта, но по некоторым причинам решил все свои статьи перезалить сюда (что бы не утерять)!
Model View Controller позволяет разделить данные, представление и обработку действий пользователя на три отдельных компонента.
•
Модель (Model). Модель предоставляет данные (обычно для View), а также реагирует на запросы (обычно от контроллера), изменяя своё состояние.
•
Представление (View). Отвечает за отображение информации (пользовательский интерфейс).
•
Поведение (Controller). Интерпретирует данные, введённые пользователем, и информирует модель и представление о необходимости соответствующей реакции.
---------------------------------------------------------------------------------------------------
Как-то задался вопросом о работе MVC, и не имея представления о реализации, я искал в гугле решение своего вопроса!
Гугл привел меня к вот этой статье
http://habrahabr.ru/blogs/php/31270/
Я поглядел на "это" все, и решил попробовать! Особого удовлетворения от работы с данной моделью я не ощущал, и решил проблему по своему...
Вот так выглядит структура моей модели:
|- /includes/
|- /includes/classes/
|- /includes/classes/MVC_BaseController.class.php
|- /includes/classes/MVC_Registry.class.php
|- /includes/classes/MVC_Router.class.php
|- /includes/classes/TestClass.class.php
|- /includes/controllers/
|- /includes/controllers/home/
|- /includes/controllers/home/index.cont.php
|- /includes/setting/
|- /includes/setting/core.inc.php
|- /.htaccess
|- /index.php
Приступим к
.htaccess
# Указываем индексный файл.
DirectoryIndex index.php
Options -Indexes
# Указываем кодировку.
AddDefaultCharset UTF-8
RewriteEngine on
# modDir: Узнаем папку к модели
# modFile: Узнаем файл модели.
# modVar: Узнаем переменные.
RewriteRule ^([a-z]{3,10})($|/)($|[a-zA-Z0-9]{3,10})($|/)($|[a-z0-9;:_]{3,30})? index.php?modDir=$1&modFile=$3&modVar=$5 [L,QSA]
Т.е теперь у нас url будет выглядеть так:
http://example.com/home/index/id:1
Переходим к
index.php
<?php
// Включаем на время отладки вывод ошибок.
error_reporting(E_ALL);
// Узнаем корневую директорию.
$pathRoot = realpath(dirname(__FILE__)).'/';
// Для ОС Windows заменяем слеш, и записываем.
define('SITE_PATH_ROOT', str_replace('\\', '/', $pathRoot));
// Подключаем конфигурационный файл.
require_once('includes/settings/core.inc.php');
На этом мы и закончим пока что работу над
index.php.
Теперь можно приступить к самой структуре MVC, и первое что мы будем делать, это класс для передачи значений в в контроллер.
Класс будет состоять из двух магических методов
__set() и
__get().
Создадим файл
/includes/classes/MVC_Registry.class.php в котором создаем класс MVC_Registry
<?php
class MVC_Registry {
// Массив с переменными.
private $_vars = array();
/**
* __set
*
* Присваиваем переменным значения.
*
* @param string $name Имя переменной.
* @param mixed $val Значение переменной.
* @return bool
**/
public function __set($name, $val)
{
if (empty($this -> _vars[$name]) == false) {
return false;
}
$this -> _vars[$name] = $val;
return true;
}
/**
* __get
*
* Возвращаем значение переменной.
*
* @param string $name Имя переменной.
* @return mixed
**/
public function __get($name)
{
if (empty($this -> _vars[$name]) == true) {
return null;
}
return $this -> _vars[$name];
}
}
?>
Теперь этот класс надо подключить в
index.php, и это мы сделаем при помощи магического метода __autoload().
Создадим файл
/includes/setting/core.inc.php и пишем в нем следующее:
<?php
function __autoload($name)
{
// Добавляем прификс к названию класса.
$fileName = $name.'.class.php';
// Узнаем категорию в которой лежит класс.
$fileDir = SITE_PATH_ROOT.'/includes/classes/'.$fileName;
// Проверяем существует ли такой класс, или нет.
if (is_file($fileDir) == false) {
return true;
}
// Подключаем файл с классом.
include_once($fileDir);
}
// Теперь можно создать объект класса MVC_Registry, что бы не гадить в index.php.
$mvcRegistry = new MVC_Registry;
?>
Перейдем к самой главной части MVC, к маршрутизатору.
Маршрутизатор у нас отвечает за то, что нам должен выдать скрипт! если точнее, то он указывает в какой папке искать модель, какой файл подключать, и что выводить.
Класс будет содержать в себе 3 метода:
__construct(), _getController(), getModul()
<?php
class MVC_Router {
// Массив со значениями.
private $_registry;
// Папка с контроллерами.
private $_path = '/includes/controllers/';
// Массив со стандартным контроллером.
private $_arrModul = array(
'dir' => 'home/',
'file' => 'index.cont.php'
);
/**
* __construct
*
* @param array $registry Массив со значениями.
*
**/
public function __construct($registry)
{
$this -> _registry = $registry;
}
/**
* _getController
*
* Узнаем путь к файлу модуля для дальнейшего его подключения.
*
**/
private function _getControllerClass()
{
// Проверяем указана ли папка с контроллером.
if (!empty($_GET['modDir'])) {
// Проверяем существует ли категория с указанным контроллером.
if (is_dir($this -> _path . $_GET['modDir'] . '/') === true) {
// Записываем указанную категорию.
$this -> _arrModul['dir'] = $_GET['modDir'] . '/';
}
// Проверяем указан ли контроллер, если он не указан, то пытаемся указать как index.
$_GET['modFile'] = empty($_GET['modFile']) ? 'index' : $_GET['modFile'];
// Проверяем существует ли файл контроллера
if (is_file($this -> _path . $this -> _arrModul['dir'] . '/' . $_GET['modFile'] . '.modul.php') === true) {
// Записываем указанный контраллер.
$this -> _arrModul['file'] = $_GET['modFile'] . '.modul.php';
}
}
// Записываем путь к файлу контроллера.
$this -> modulFile = SITE_PATH_ROOT . $this -> _path . $this -> _arrModul['dir'] . $this -> _arrModul['file'];
}
/**
* getModul
*
* Подключаем класс модуля, и выводим результат.
*
**/
public function getController()
{
// Узнаем путь к контроллеру.
$this -> _getControllerClass();
// Подключаем контроллер.
include_once ($this -> modulFile);
// Создать объект класса DisplayController
$controller = new DisplayController($this -> _registry);
// Выводим результат выполнения контроллера.
$controller -> display();
}
}
?>
Теперь в файле
index.php добавим еще пару строк? в которых мы запускаем маршрутизатор, и выводим контроллер.
<?php
// Создадим объект класса MVC_Router
$mvcRouter = new MVC_Router($mvcRegistry);
// Подключаем контроллер.
$mvcRouter -> getController();
?>
Все готово! Теперь можно создавать контроллер!
Думаю у вас возник вопрос "Неужели нам придется каждый раз создавать конструктор класса DisplayController?", конечно же нет!
Создаем файл
/includes/classes/MVC_BaseController.class.php в котором мы создадим абстрактный класс MVC_BaseController который будет выполнять не только подгрузку значений реестра, но и разберать переменные полученные из $_GET.
<?php
abstract class MVC_BaseController {
// Массив со значениями.
protected static $registry = array();
/**
* __construct
*
* @param array $registry Массив со значениями.
*
**/
public function __construct($registry)
{
self :: $registry = $registry;
// Проверяем указанны ли переменные.
if (empty($_GET['modVar']) === false) {
// Делим строку на части.
$aExVar = explode(';', $_GET['modVar']);
// Если в строке есть хоть одна переменная, то работаем дальше.
if (empty($aExVar) === false) {
$vars = array();
foreach ($aExVar as $aKey) {
// Делим строку на ключ и значение.
$aExValue = explode(':', $aKey);
// Проверяем есть ли в строке ключ и значение.
if (empty($aExValue[0]) === false and empty($aExValue[1]) === false) {
// Записываем переменную.
$vars[$aExValue[0]] = $aExValue[1];
}
}
}
// Пишем полученные переменные в глобальный массив $_GET
$_GET = array_map('trim', $vars);
}
}
// Указываем метод displey() как абстрактный.
abstract function display();
}
?>
Самое главное мы сделали, осталось дело за малым! Создаем файл контроллера
/includes/controllers/home/index.cont.php
И в нем мы пишем следующее:
<?php
class DisplayController extends MVC_BaseController {
public function display()
{
echo 'Hello World';
}
}
?>
Посмотрев на работу скрипта, результатом у нас будет:
Hello World
Теперь можно глянуть применение:
/index.php
<?php
define('SITE_PATH_ROOT', str_replace('\\', '/', realpath(dirname(__FILE__))).'/');
include_once ('includes/settings/core.inc.php');
$mvcRegistry -> testClass = new TestClass();
$mvcRouter = new MVC_Router($mvcRegistry);
$mvcRouter -> getController();
?>
/includes/classes/TestClass.class.php
<?php
class TestClass {
public function testMethod($str)
{
return 'I love '.$str;
}
}
?>
/includes/controllers/home/index.cont.php
<?php
class DisplayController extends MVC_BaseController {
public function display()
{
echo 'Hello World <br />' . self :: $registry -> testClass -> testMethod('Moscow');
}
}
?>
Результат выполнения:
Hello World
I love Moscow
------------------------------------
Подготовил статью:
Nu3oN специально для
http://7je.ru
URL:
https://visavi.net/articles/365