Закрыть Авторизация

     

Система "Модель-Вид-Контроллер"

Содержание

 

1. Введение

2. Требования

3. Введение в систему "Модель-Вид-Контроллер"

3.1. "Модель"

3.2. "Вид"

3.3. "Контроллер"

3.4. 5 базовых компонент MVC и их взаимосвязи

4. Joomla! MVC реализация

5. Создание компонент

5.1. Соглашения об именах

5.2. Создание файла - точки входа

5.3. Создание компоненты "Контроллер"

5.4. Создание компоненты "Вид"

5.4.1. Пример

5.5. Результат – создание файла hello.xml

6. Создание Модели

7. Использование Модели

7.1. Добавление файла в пакет

8. Заключение

9. Статьи по данной теме

 

1. Введение

Инструментальная среда (framework) является основой для разработки программных Web-приложений. Подобных сред несколько, но Joomla! 1.5 является одной из самых мощных, в первую очередь благодаря гибкой расширяемости своего кода. Данное описание демонстрирует процесс использования компонент среды.

В 1-ой части описания приводится пример разработки простой компоненты Hello World!. В последующих данный пример вырастет, чтобы показать всю мощь и гибкость предлагаемой системы MVC, функционирующей в среде Joomla!.

 

2. Требования

Для реализации предлагаемых решений требуется версия Joomla! 1.5 или выше.

 

3. Введение в систему MVC

pic1-part1

Идея создания базовых компонент с возможностью быстрого наращивания кода, обеспечивающего новые функции как обработки данных, так и интерфейса, кажется довольно простой. Подобной системой и является предлагаемая.

Система "Модель-Вид-Контроллер" (Model-View-Controller, далее просто MVC) – программный шаблон для организации кода, который может использоваться в таких прикладных областях как логистика и представление данных. Именно в логистике сначала принято поставить задачи и определить пути их решения ("Контроллер"), затем определить круг имеющегося материала для решения задач ("Модель"), и, в конце концов, договориться с контрагентами для решения задач (определить интерфейс – "Вид") при минимальном влиянии на ранее принятые пути решения. MVC изначально была разработана для отражения традиционного ввода, обработки и вывода в логической GUI-архитектуре.

Приведенные 3 задачи (ввод, обработка, вывод) являются основой предлагаемой системы Joomla MVC. В 1-ой части все 3 задачи описаны кратко, для получения большей информации можно обратиться к следующим частям описания.

 

3.1. "Модель"

"Модель" – компонента, включающая в себя данные приложения. Часто в "Модели" находятся и методы для управления и манипулирования этими данными, помимо методов собственно получения данных из "Модели". В нашем случае, "Модель" содержит методы для добавления, удаления и изменения информации о приветствиях в базе данных. Кроме того, наша "Модель" содержит методы для получения из базы списка возможных приветствий. И главное, в "Модель" встроен контроль доступа к данным. Таким образом, если предполагается использование приложения в другой прикладной системе для работы с другой базой данных, именно компонента "Модель" является изменяемой частью системы MVC, что недопустимо ни с "Видом", ни с "Контроллером".

 

3.2. "Вид"

"Вид" – компонента преобразовывает данные, полученные от "Модели", в форму, удобную для интерфейса с пользователем. В Web-приложениях "Вид" – главным образом HTML-страница. "Вид" получает данные от "Модели" (через "Контроллер") и направляет их в интерфейс пользователя. Данная компонента ни при каких обстоятельствах не может стать причиной изменения базы данных, она служит только для вывода данных, полученных от "Модели".

 

3.3. "Контроллер"

"Контроллер" – компонента, отвечающая за взаимоотношения с пользователем. В случае с Web-приложением – за запрос пользователем новой страницы сайта (в основном). "Контроллер" определяет тип запроса пользователя, сообщает "Модели" о необходимой обработке и передает данные компоненте "Вид". "Контроллер" не производит вывод данных, он вызывает только те методы "Модели", которые изменяют эти данные, и направляет их уже компоненте "Вид" для собственно вывода.

 

3.4. 5 базовых компонент MVC и их взаимосвязи

pic2-part1

На рисунке приведены базовые компоненты системы MVC Joomla. В виде маленького голубого кружка представлен дополнительной создаваемый элемент – точка входа в систему MVC (Entry Point). Кроме того, компонента "Вид" снабжается элементом "Шаблон". Пониманию взаимоотношений приведенных 5 базовых компонент и посвящено данное описание системы Joomla! MVC.

1-ая часть данного описания ориентируется только на компоненты "Контроллер" и "Вид" (с соответствующим примером), обозначенные на схеме голубым. 2-ая часть вводит, а 3-тья описывает более подробно компоненту "Модель" для манипулирования данными (компонента на схеме – зеленым).

Необходимо иметь в виду, что приводимая простая схема относится к визуальному результату Web-разработчика – собственно сайту (уровень front-end). Аналогичная схема может быть создана и для целей администрирования сайта (уровень back-end). Администрирование разбирается в 4-6 частях данного описания. Оба уровня разработки создаются и конфигурируются с помощью установочного XML-файла (обычно называемого "манифестом").

 

4. Joomla! MVC реализация

В Joomla! система MVC реализована 3-мя классами : JModel, JView и JController. Подробности описания данных классов можно найти в соответствующей API-документации (WIP).

С целью облегчения изучения и отладки, возможно будет хорошим решением с вашей стороны добавить на свой Joomla!-сайт отладчик. Хорошим примером для изучения является проект J!Dump, компоненту вывода которого скорее всего Вы сможете использовать даже без изменений. J!Dump позволит Вам просмотреть не только свойства системы, но и ее методы.

 

5. Создание компонент

Для создания основных компонент требуется только 5 файлов:

  • site/hello.php – входная точка нашей системы
  • site/controller.php – файл содержит компоненту "Контроллер"
  • site/views/hello/view.html.php – файл содержит необходимые данные и посылает их в пример
  • site/views/hello/tmpl/default.php – файл примера
  • hello.xml – XML-файл (манифест), сообщающий Joomla! о порядке установки компонент.

Не забудьте, имя файла-точки входа компоненты должно совпадать с именем самой компоненты. Например, если вы назвали комоненту "Very Intricate Name Component", при установке (см. ниже раздел hello.xml) Joomla! создаст папку com_veryintricatenamecomponent, а файл точки входа должен иметь имя veryintricatenamecomponent.php, иначе работа будет невозможна.

Не забудьте, что некоторые специальные символы (например, нижнее подчеркивание '_') могут использоваться Joomla для своих целей, поэтому их использование для своих имен компонент и файлов стоит избегать.

Папка "site" является частью создаваемой компоненты и создается при установке на уровне front-end.

 

5.1. Соглашения об именах

Важно знать, что некоторые слова зарезервированы для использования в компонетах и их классах, поэтому произвольное использование данных имен может приводить к ошибкам, порой фатальным в работе отладчика. Одним из зарезервированных слов является "view" (в любом регистре) – для класса компоненты "Вид" (подкласс JView) и класса компоненты "Контроллер" (подкласс JController), так как этот класс необходим для получения первой части имени компоненты, совпадающей с именем класса (хотя это условие и не является обязательным, его нарушение не вызывает ошибки, это просто полезное соглашение).

Все имена файлов и папок создаваемых компонент должны быть представлены в нижнем регистре для их успешной работы в системах Unix/Linux.

 

5.2. Создание файла - точки входа

Joomla! всегда предоставляет доступ через одну точку входа : index.php – для сайта или administrator/index.php – для приложения администратора. Сайт (прикладное приложение) может затем загружать любые необходимые компоненты на основе информации в параметре 'option' URL или в данных формы сайта, принятых по методу POST. Для нашей компоненты URL имеет вид:

index.php?option=com_hello&view=hello

Приводимый URL обеспечит загрузку нашего главного файла, который и является точкой входа создаваемой компоненты : components/com_hello/hello.php.

Код данного файла имеет типичный для всех компонент вид.
site/hello.php:

<?php
/**
* @package Joomla.Tutorials
* @subpackage Components
* components/com_hello/hello.php
* @link http://docs.joomla.org/Developing_a_Model-View-Controller_Component_-_Part_1
* @license GNU/GPL
*/

// проверка на доступ

defined( '_JEXEC' ) or die( 'Restricted access' );

// требование основного контроллера

require_once( JPATH_COMPONENT.DS.'controller.php' );

// требование дополнительного контроллера, при необходимости

if($controller = JRequest::getWord('controller')) {
$path = JPATH_COMPONENT.DS.'controllers'.DS.$controller.'.php';
if (file_exists($path)) {
require_once $path;
} else {
$controller = '';
}
}

// создание контроллера

$classname = 'HelloController'.$controller;
$controller = new $classname( );

// выполнение требуемой задачи

$controller->execute( JRequest::getWord( 'task' ) );

// перенаправление контроллера

$controller->redirect();


Первая строка – проверка системы безопасности.
JPATH_COMPONENT – абсолютный путь к текущей компоненте, в нашем случае к - components/com_hello. Если специально необходима компонента сайта или администратора, мож-но использовать пути JPATH_COMPONENT_SITE или JPATH_COMPONENT_ADMINISTRATOR.
DS – зарезервированное символическое имя разделителя в представлении пути ('/' или '\'). Необходимый разделить, используемый в операционной системе компьютера, инструментальная среда определяет автоматически, поэтому разработчику не стоит беспокоиться об этом. Константа 'DS' должна всегда использоваться при работе на локальном сервере.
После загрузки базового контроллера происходит проверка необходимости специального контроллера. В нашей создаваемой компоненте базовый контроллер является единственным, но мы оставляет данную часть кода для использования в будущем.
Метод JRequest:getWord() производит поиск необходимого слова в URL или POST-данных. Таким образом, если наш URL имеет вид index.php?option=com_hello&controller=controller_name, мы можем получить имя контроллера нашей компоненты командой : echo JRequest::getWord('controller');
В предлагаемом примере имя контроллера 'HelloController' в файле com_hello/controller.php, а, при необходимости, дополнительные контроллеры имеют имена 'HelloControllerController1' в файле com_hello/controllers/controller1.php. Используя эту стандартную схему имен, позднее мы легко сможем получать имена конкатенацией : '{Componentname}{Controller}{Controllername}'
После создания контроллера мы требуем от него выполнить задачу, определенную в параметре "task" URL : index.php?option=com_hello&task=sometask. Если задача не определена явно, по умолчанию используется задача по имени 'display'. Задача по умолчанию использует информацию для вывода из параметра 'view' URL. Другими возможными выполняемыми задачами являются "save", "edit", "new" и некоторые другие.
Контроллер может решить перенаправить страницу, обычно по завершении задачи сохранения 'save', что всегда рекомендуется с большой осторожностью.
Главная точка входа в компоненту (в нашем случае – файл hello.php) обеспечивает данные для контроллера, который управляет выполнением задачи из запроса.
Заметим, что мы не используем в данном файле закрывающей тег php : ?>. Причина состоит в том, что в нашем выходном коде нет каких-либо нежелательных пробелов. Это практика по умолчанию, принятая в Joomla! 1.5, которая будет использоваться нами во всех php-файлах.

 

 

5.3. Создание компоненты "Контроллер"

Наша создаваемая на основе базовых компонента имеет толькот одну задачу – приветствие мира. Таким образом, контроллер довольно прост – никаких преобразований данных не требуется. Все что необходимо – это загрузить выводимую информацию. В контроллере только один метод : display(). Большинство требований функциональности уже встроено в класс JController, поэтому единственное, что требуеися, это вызвать метод JController::display().
Код базовой компоненты "Контроллер" находится в файле site/controller.php :


<?php
/**
* @package Joomla.Tutorials
* @subpackage Components
* @link http://docs.joomla.org/Developing_a_Model-View-Controller_Component_-_Part_1
* @license GNU/GPL
*/

// Проверка на доступ

defined( '_JEXEC' ) or die( 'Restricted access' );

jimport('joomla.application.component.controller');

/**
* контроллер компоненты Hello World
* @package Joomla.Tutorials
* @subpackage Components
*/

class HelloController extends JController
{ /**
* метод вывода на экран
* @access public
*/
function display()
{ parent::display();
}
}

 

Конструктор Jcontroller будет всегда создавать по умолчанию метод display(), пока не будет опре-делен другой (с помощью метода registerDefaultTask()).
Предлагаемый метод display() не существует, пока не будет вызван его родительский конструктор. Тем не менее, он полезен для понимания процессов, происходящих в контроллере.
Метод JController::display() определяет имя компоненты "Вид" и содержимое из запроса и загру-жает как саму компоненту, так и ее содержимое. После создания пункта меню вашей компоненты. Менеджер меню позволит администратору выбрать компоненту "Вид", связанную с меню, и соот-ветствующее содержимое для вывода. Обычно производится вывод целого набора данных (напри-мер, списка машин, событий). Содержимое вывода определяет организацию компоненты "Вид".
В нашем случае, мы выводит одну строку приветствия, таким образом и содержимое представляет собой однострочный текст, что принимается по умолчанию.

5.4. Создание компоненты "Вид"

 

Задача компоненты "Вид" очень проста : она получает данные для вывода и направляет их в "Шаблон" с помощью метода JView::assignRef.
Замечание : ключ (первый аргумент), передаваемый методу assignRef не должен начинаться с сим-вола '_' (нижнее подчеркивание), например, $this->assignRef('_greeting',$greeting). Иначе ме-тод возвращает ошибку (false) и переменная не будет передана в "Шаблон".

Код компоненты "Вид" в файле site/views/hello/view.html.php :

<?php
/**
* @package Joomla.Tutorials
* @subpackage Components
* @link http://docs.joomla.org/Developing_a_Model-View-Controller_Component_-_Part_1
* @license GNU/GPL
*/

// проверка на доступ

defined( '_JEXEC' ) or die( 'Restricted access' );

jimport( 'joomla.application.component.view');

/**
* класс HTML View для компоненты HelloWorld
* @package HelloWorld
*/

class HelloViewHello extends JView
{ function display($tpl = null)
{ $greeting = "Hello World!";
$this->assignRef( 'greeting', $greeting );
parent::display($tpl);
}
}

 

5.4.1 Пример

 

Файл примера - обычный PHP-файл, использующий данные компоненты "Вид" обычным образом. Переменные, определяемые в методе JView::assignRef, могут быть доступны из примера с исполь-зованием $this : $this->{имя переменной} (см. пример кода ниже).

Наш пример очень прост : мы хотим только вывести на экран привествие от компоненты "Вид" – файл site/views/hello/tmpl/default.php :


<?php
// Проверка на доступ
defined('_JEXEC') or die('Restricted access'); ?>
<h1><?php echo $this->greeting; ?></h1>

5.5. Результат – создание файла hello.xml

 

Возможна установка компонент вручную копированием соответствующих файлов с помощью FTP-клиента и изменением таблиц базы данных. Но более эффективно - создать пакетный файл, чтобы Joomla! Installer сделал это за вас. Этот файл содержит информацию :
•    описание основных компонент (например, имена);
•    описание, авторские права, лицензию;
•    список файлов для копирования;
•    дополнительно, PHP-файл, содержащий дополнительные операции при установке и удалении;
•    дополнительно, SQL-файл с запросами к базе данных, которые должны быть выполнены при уста-новке и удалении.

Содержимое XML-файла hello.xml следующее :

<?xml version="1.0" encoding="utf-8"?>
<install type="component" version="1.5.0">
<name>Hello</name>

<!—Следующие элементы носят дополнительный характер и доступны к изменениям -->

<creationDate>2007-02-22</creationDate>
<author>John Doe</author>
<authorEmail>Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра.</authorEmail>
<authorUrl>http://www.example.org</authorUrl>
<copyright>Copyright Info</copyright>
<license>License Info</license>

<!-- строка версии, записываемая в таблицу компонент -->

<version>1.01</version>

<!-- дополнительное описание – по умолчанию содержит имя компоненты -->

<description>Description of the component ...</description>

<!-- пути размещения файлов -->
<!-- замечание по поводу папок : копирование производится из папки,
/site/, входящей в папку пакетного файла -->

<files folder="site">
<filename>controller.php</filename>
<filename>hello.php</filename>
<filename>index.html</filename>
<filename>views/index.html</filename>
<filename>views/hello/index.html</filename>
<filename>views/hello/view.html.php</filename>
<filename>views/hello/tmpl/default.php</filename>
<filename>views/hello/tmpl/index.html</filename>
</files>

<administration>

<!-- раздел меню администратора -->

<menu>Hello World!</menu>

<!-- пути к файлам администратора -->

<files folder="admin">
<filename>hello.php</filename>
<filename>index.html</filename>
</files>

</administration>
</install>



Важно ! Расположите этот xml-файл, также называемый манифестом, в папку пакетного файла (так как программа установки именно эту папку будет рассматривать как корневую).

Вы можете заметить, что вне обсуждения остались файлы index.html и admin files. Index.html размещается в каждой папке для устранения необходимости пользователю обращаться к списку папок. Если файл index.html отсутствует, некоторые Web-серверы начинают анализировать список папок сайта, что часто очень неудобно.

Эти файлы содержат одну единственную строку :

<html><body bgcolor="#FFFFFF"></body></html>

 

 

Данный код обеспечит вывод чистой страницы.
Файл hello.php в папке администратора является точкой входа для наших компонент со стороны администратора. Пока компоненты не требуют администрирования, содержимое данного файла совпадает с содержимым файла index.html.

Проверить всю проведенную работу вы можете обратившись на URL index.php?option=com_hello.

6. Создание модели

 

Концепция компонента Модель предполагает наличие у него имени, которое и обеспечит в будущем вызов компонента. В нашем случае наша первая Модель имеет имя 'hello'.
Принцип создания имен классов Моделей в среде Joomla! следующий : сначала имя компонента (у нас 'hello'), затем имя 'model' и по завершении имя Модели. Таким образом, имя класса нашей Модели - HelloModelHello.
Пока наша Модель обладает одним поведением – получение приветствия, и, таким образом, одним методом getGreeting(). Метод просто возвращает строку 'Hello, World!'.

Соответствующий код в файле site/models/hello.php :

<?php
/**
* Hello Model for Hello World Component
* @package Joomla.Tutorials
* @subpackage Components
* @link http://docs.joomla.org/Developing_a_Model-View-Controller_Component_-_Part_2
* @license GNU/GPL
*/

// Проверка на доступ

defined( '_JEXEC' ) or die( 'Restricted access' );

jimport( 'joomla.application.component.model' );

/**
* Hello Model
* @package Joomla.Tutorials
* @subpackage Components
*/

class HelloModelHello extends JModel
{ /**
* Получение приветствия
* возвращаемая строка приветствия будет выведена на экран пользователя
*/
function getGreeting()
{ return 'Hello, World!';
}
}

 

Обращаем внимание на функцию jimport, которая необходима для загрузки файла /libraries/joomla/application/component/model.php из среды Joomla!, необходимого для нашего компонента. Точки в записи параметра функции используются как разделители папок, а после последней точки указано имя загружаемого файла. Все файлы имеют адресацию  относительно папки libraries. Загружаемый файл содержит класс-родитель класса JModel, так как последний является его расширением.
Теперь после создания Модели, мы должны изменить компонент Вид, чтобы он мог принимать приветствие.

7. Использование модели

 Среда Joomla! настроена таким образом, что Контроллер будет автоматически загружать Модель, если она имеет то же имя, что и компонент Вид, и будет связывать эти два компонента. Так как наш компонент Вид называется 'Hello', наша Модель 'Hello' будет загружена автоматически. Поэтому мы можем легко вызывать методы Модели из Вида, получив ссылку на Модель методом JView::getModel() (если вы не будете следовать приведённому соглашению имен, то при вызове метода JView::getModel() ему необходимо передать имя Модели).


Код нашего предыдущего компонента Вид содержал строку :
$greeting = "Hello World!";

Для соответствия нашему новому компоненту Модель, мы изменяет эту строку на :
$model = &$this->getModel();
$greeting = $model->getGreeting();

Код компонента Вид становится следующим :


<?php
/**
* @package Joomla.Tutorials
* @subpackage Components
* @link http://docs.joomla.org/Developing_a_Model-View-Controller_Component_-_Part_2
* @license GNU/GPL
*/

// Проверка на доступ

defined( '_JEXEC' ) or die( 'Restricted access' );

jimport( 'joomla.application.component.view');

/**
* класс HTML View для компонента HelloWorld
* @package HelloWorld
*/

class HelloViewHello extends JView
{ function display($tpl = null)
{ $model = &$this->getModel();
$greeting = $model->getGreeting();
$this->assignRef( 'greeting', $greeting );
parent::display($tpl);
}
}

 

7.1. Добавление файла в пакет

 Все, что осталось, это добавить информацию в XML-файл, чтобы наша новая Модель была скопирована. Среда Joomla! будет искать нашу модель в папке моделей, поэтому после добавления строки в раздел site, проблем с поиском не возникнет :

<filename>models/hello.php</filename>
Наш новый файл hello.xml будет выглядеть следующим образом :

<?xml version="1.0" encoding="utf-8"?>
<install type="component" version="1.5.0">
<name>Hello</name>

<!-- Следующие элементы носят дополнительный характер и доступны к изменениям -->

<creationDate>2007-02-22</creationDate>
<author>John Doe</author>
<authorEmail>Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра.</authorEmail>
<authorUrl>http://www.example.org</authorUrl>
<copyright>Copyright Info</copyright>
<license>License Info</license>

<!-- строка версии, записываемая в таблицу компонент -->

<version>1.01</version>

<!-- дополнительное описание – по умолчанию содержит имя компоненты -->

<description>Description of the component ...</description>

<!-- необходимые файлы и путь их размещения -->
<!-- замечание по поводу папок : копирование производится из папки,
/site/, входящей в папку пакетного файла -->

<files folder="site">
<filename>controller.php</filename>
<filename>hello.php</filename>
<filename>index.html</filename>
<filename>models/hello.php</filename>
<filename>models/index.html</filename>
<filename>views/index.html</filename>
<filename>views/hello/index.html</filename>
<filename>views/hello/view.html.php</filename>
<filename>views/hello/tmpl/default.php</filename>
<filename>views/hello/tmpl/index.html</filename>
</files>
<administration>

<!-- раздел меню администратора -->

<menu>Hello World!</menu>

<!-- файлы администратора и их папка -->

<files folder="admin">
<filename>hello.php</filename>
<filename>index.html</filename>
</files>
</administration>
</install>

 

8. Зключение

Мы создали простой компонент модели MVC. Каждый ее элемент пока довольно прост, но, тем не менее, уже обладает присущей Joomla! гибкости и мощности.

9. Статьи по данной теме

Система Модель-Вид-Контроллер - Часть 1
Система Модель-Вид-Контроллер - Часть 2 – Добавление модели 
Система Модель-Вид-Контроллер - Часть 3 – Использование базы данных
Система Модель-Вид-Контроллер - Часть 4 – Создание интерфейса администратора
Система Модель-Вид-Контроллер - Часть 5 – Основые компоненты среды
Система Модель-Вид-Контроллер - Часть 6 – Добавление действий среды

 

 

Загрузка

Компонент может быть загружен с com_hello2_01


 

 

 

 

 

 

 

 

 

 

 

/**
* @package Joomla.Tutorials
* @subpackage Components
* components/com_hello/hello.php
* @link http://docs.joomla.org/Developing_a_Model-View-Controller_Component_-_Part_1
* @license GNU/GPL
*/

// проверка на доступ

defined( '_JEXEC' ) or die( 'Restricted access' );

// требование основного контроллера

require_once( JPATH_COMPONENT.DS.'controller.php' );

// требование дополнительного контроллера, при необходимости

if($controller = JRequest::getWord('controller')) {
$path = JPATH_COMPONENT.DS.'controllers'.DS.$controller.'.php';
if (file_exists($path)) {
require_once $path;
} else {
$controller = '';
}
}

// создание контроллера

$classname    = 'HelloController'.$controller;
$controller   = new $classname( );

// выполнение требуемой задачи

$controller->execute( JRequest::getWord( 'task' ) );

// перенаправление контроллера

$controller->redirect();

Подпишись!