MVC и PHP, часть 1
Принцип Модель-Представление-Контроллер (Model-View-Controller, MVC) был сформулирован еще в конце 70-х годов XX века. Это архитектура построения программного обеспечения, при которой данные независимы от методов, которые с ними работают.
Теоретически, грамотно построенная MVC-система должна позволять фронтэнд - и бэкэнд-разработчикам работать над одним проектом без необходимости работать над одними и теми же файлами одновременно.
Несмотря на то, что изначально MVC был разработан для локальных приложений, позже он был адаптирован и широко распространился среди веб-разработчиков из-за акцента на разделение функций, и возможностей повторного использования кода.
MVC поощряет разработку модульных систем, позволяя быстро модифицировать проект, добавлять и удалять функционал.
В этой статье будут рассмотрены базовые принципы подхода MVC, дано определение этому понятию и разобраны небольшие примеры на PHP.
Целевая аудитория – все те, кто раньше никогда не создавал MVC-программы, а также те, кто хочет укрепить свои знания по этой теме.
Понятие MVC
В название принципа входит три основополагающих компонента: модель (Model), представление (View) и контроллер (Controller).
Визуальное представление завершенного и корректного MVC-приложения выглядит так, как показано ниже:

Изображение демонстрирует прохождение одиночного потока данных через все компоненты и их взаимное отношение друг к другу.
Модель
Название «модель» обозначает хранилище данных, используемых во всей конструкции. Оно должно предоставлять доступ к данным для их просмотра и изменения. Модель является своего рода мостом между представлением и контроллером.
Одним из важных аспектов модели является то, что технически она «слепа» и не имеет представления о том, что происходит с данными, когда они проходят через представление или контроллер.
Модель не вызывает и не ожидает ответа от других компонентов, а просто обрабатывает данные в своем хранилище и готовит их к отправлению другим компонентам.
Модель, тем не менее, не может быть названа базой данных или шлюзом другой системы, которая управляет процессом обработки данных. Модель должна работать как сторож данных, не задавая вопросов и отвечая на все приходящие запросы.
Зачастую наиболее сложной частью системы MVC является именно модель - связующее звено между контроллером и представлением.
Представление
Этот компонент отображает данные, полученные из модели, в определенном виде. Традиционно, в веб-приложениях использующих MVC, представление является набором HTML-файлов, которые и формируют облик выводимых данных.
Представление также определяет реакцию пользователя, который затем взаимодействует с контроллером. Простейшим примером этого может служить кнопка, сгенерированная представлением, по которой кликает пользователь, тем самым запуская взаимодействие с контроллером.
Среди веб-разработчиков, использующих MVC, существуют некоторые заблуждения относительно компонента представления.
Например, о том, что представление не имеет никакой связи с моделью, а все данные, отображаемые представлением, проходят через контроллер. В действительности, описанное выше, полностью идет в разрез с концепцией MVC.
Более того, описание представления как файла шаблона неверно. Однако, как заметил Tom Butler, это не ошибка какого-то одного человека, а совокупность заблуждений многих разработчиков, неверно усвоивших теорию MVC. А затем они передают свой опыт другим, что сами понимаете к чему ведет.
Представление, на самом деле, это нечто большее, чем просто шаблон. Но современное понимание, породившее множество фреймворков, настолько исказило изначальный смысл, что разработчики уже не особо заботятся о соблюдении принципов MVC.
Также стоит заметить, что представление никогда не получает данные из контроллера. Как было замечено при обсуждении модели, прямой связи между представлением и контроллером, минуя модель, нет.
Контроллер
Завершает триаду компонентов контроллер. Его функция заключается в управлении данными, вводимыми и отправляемыми пользователем, а также соответствующее обновление модели.
Источником, приводящим в движение контроллер, является пользователь; без взаимодействия с ним, существование контроллера не имеет смысла. Это единственная часть MVC, с которой напрямую имеет дело пользователь.
Контроллер можно описать как сборщик информации, который передает её на хранение модели, и не содержит других логических компонентов, кроме тех, которые нужны для приема вводимых данных.
Также, контроллер подключен только к одной модели и одному представлению, что делает его единственным каналом прохождения данных в системе, который поддерживает механизмы обеспечения безопасности передачи.
Контроллер активен только тогда, когда пользователь взаимодействует с представлением. Иными словами, пользователь, работая с представлением, по принципу триггера запускает контроллер.
Распространенной среди разработчиков ошибкой является присвоение контроллеру функций, которые должно иметь представление.
Это результат того, что некоторые разработчики считают представление просто шаблоном. В дополнение ко всему, ошибкой является придавать контроллеру функции, делающие его единственным ответственным за передачу и обработку данных от модели к представлению, в то время как в MVC эта ответственность должна распределяться между моделью и представлением.
MVC в PHP
Давайте напишем веб-приложение на PHP, которое будет использовать MVC.
Начнем с простейших примеров:
<?php
class Model
{
public $string;
public function __construct(){
$this->string = "MVC + PHP = Awesome!";
}
}
<?php
class View
{
private $model;
private $controller;
public function __construct($controller,$model) {
$this->controller = $controller;
$this->model = $model;
}
public function output(){
return "<p>" . $this->model->string . "</p>";
}
}
<?php
class Controller
{
private $model;
public function __construct($model) {
$this->model = $model;
}
}
Для начала, мы создали несколько базовых классов для каждой части нашей реализации MVC.
Теперь настроим отношения между ними:
<?php
$model = new Model();
$controller = new Controller($model);
$view = new View($controller, $model);
echo $view->output();
Как можно было заметить в примере выше, мы не создавали специфического функционала контроллера, потому что отсутствует взаимодействие пользователя с нашим приложением.
Представление хранит все функции, что сделано исключительно в демонстрационных целях.
Давайте теперь расширим наш пример, чтобы показать как добавить функциональность в контроллер и придать интерактивности нашему приложению:
<?php
class Model
{
public $string;
public function __construct(){
$this->string = “MVC + PHP = Awesome, click here!”;
}
}
<?php
class View
{
private $model;
private $controller;
public function __construct($controller,$model) {
$this->controller = $controller;
$this->model = $model;
}
public function output() {
return '<p><a href="mvc.php?action=clicked"'> . $this->model->string . "</a></p>";
}
}
<?php
class Controller
{
private $model;
public function __construct($model){
$this->model = $model;
}
public function clicked() {
$this->model->string = “Updated Data, thanks to MVC and PHP!”
}
}
Мы расширили наше приложение.
Отношения между нашими компонентами теперь выглядят так:
<?php
$model = new Model();
$controller = new Controller($model);
$view = new View($controller, $model);
if (isset($_GET['action']) && !empty($_GET['action'])) {
$controller->{$_GET['action']}();
}
echo $view->output();
После запуска кода, кликните по ссылке, и вы сможете увидеть строку с измененными данными.
Заключение
Мы рассмотрели основы MVC и создали простейшее приложение на основе этой архитектуры, но впереди еще долгий путь, прежде чем мы получим желаемый результат.