22 Июнь 2011

HMVC в Kohana 3

HMVC в Kohana 3

У данной публикации есть спонсор (как им стать):

В связи с запуском новой площадки хостинг-компания Inferno Solutions предлагает 50% скидку на весь срок аренды любого Linux VPS в Эстонии тем клиентам, которые сделают заказ до 1 июля! Используйте код скидки EST50. Отзывы о компании.

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

Если вы не знакомы с фреймворком Kohana 3, то специально для вас у меня есть бесплатный видеокурс. Переходите к первому уроку по Kohana.

Сегодня речь пойдет о технологии HMVC, поддерживаемой Kohana.

Технология HMVC (иерархический MVC) позволяет обратиться из вида или контроллера одной страницы сайта, к контроллеру другой страницы. В результате мы получаем возможность отображать стандартные блоки (блоки новостей, рекламные блоки), формируемые одним контроллером, на любой странице сайта, формируемой совершенно другим контроллером.

Плюсы HMVC-подхода:

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

Постановка задачи: блок новостей, формируемый контроллером news (kohana\www\application\classes\controller\news.php), необходимо встроить в главную страницу сайта (ну и во все те страницы, где нужен блок новостей, см. рис. 1).

Принцип HMVC

Рис 1. Реализация поставленной задачи посредством HMVC.

Листинг 1. Контроллер News (kohana\www\application\classes\controller\news.php)

<?php defined('SYSPATH') or die('No direct script access.');

class Controller_News extends Controller {

	public function action_index()
	{	
		$news = new Model_News();
		$data['contentNews'] = $news->get3news();

		$this->response->body(View::factory('newsview', $data));
	}

}

Пояснения к листингу 1

7-я строка. Создается экземпляр модели News, функционал которой мы опишем чуть позже.

8-я строка. В поле contentNews массива data методом get3news() записывается 3-и новости из таблицы news базы данных (функционал метода get3news() будет описан чуть позже).

10-я строка. Несколько иным способом формируется отображение, поскольку мы наследуем контроллер News от Controller (3-я строка листинга 1), а не от Controller_Template (как обычно я это делал в видеуроках). От Controller_Template нет смысла наследовать, т. к., в данном случае, мы не применяем сборку внешнего вида из базового шаблона и внутреннего шаблона, мы просто формируем внешний вид посредством единственного файла kohana\www\application\views\newsview.php.

Листинг 2. Модель News kohana2\www\application\classes\model\news.php

<?php defined('SYSPATH') or die('No direct script access.');

class Model_News
{	
	public function get3news()
	{
		return DB::select()
		->from('news')
		->limit('3')
		->execute()
		->as_array();
	}
}

Пояснение к листингу 2:

Метод get3news() возвращает в виде ассоциативного массива три новости из таблицы news (структура таблицы news представлена на рис. 2).

Структура таблицы news MySQL базы данных

Рис 2. Структура таблицы news.

Листинг 3. Файл вида kohana\www\application\views\newsview.php

<p>Блок новостей</p>

<?foreach($contentNews as $item){?>
<p><?=$item['short-content']?></p>
<?}?>

Пояснение к листингу 3

В файле вида происходит вывод в цикле содержимого поля short-content таблицы news. Иными словами, произойдет вывод короткого описания трех новостей, которые мы достали из базы данных методом get3news() (см. листинг 2).

Последнее, что осталось сделать — это осуществить вывод получившегося блока с тремя новостями (листинг 3) в любой другой файл вида.

Предположим, я хочу вывести новости над формой авторизации (kohana/auth). Для этого в начало файла вида авторизационной страницы (kohana\www\application\views\authview.php) необходимо добавить код вызова контроллера News, представленный в листинге 4:

Листинг 4. Код вызова контроллера News

<?
$request = Request::factory('news');
$response = $request->execute();
echo $response;
?>

Результат представлен на рис. 3.

Результат применения HMVC

Рис. 3. Результат вызова контроллера News в виде авторизационной страницы.

Есть одна небольшая проблема — посетитель сайта запросто может набрать адрес kohana/news и увидеть голый блок новостей.

Эту проблему можно побороть в два счета:

  • Имеется возможность проверить первичный ли запрос поступил к контроллеру (под первичным мы понимаем запрос от пользователя, перешедшего по адресу kohana/news) или котроллер News запрашивается другим контроллером.
  • Если запрос первичен, то мы отобразим страницу 404 (как реализовать страницу 404 в Kohana 3).

Для этого в начало контроллера News добавим метод before, который осуществит проверку на первичность запроса перед обработкой экшена index (см. листинг 5).

Листинг 5. Метод before для проверки первичности запроса к контроллеру

<?php defined('SYSPATH') or die('No direct script access.');

class Controller_News extends Controller {

	public function before()	
	{
		if($this->request->is_initial())
		{
			throw new HTTP_Exception_404('File not found!');
		}
	}

	public function action_index()
	{	
		...

С уважением, Андрей Морковин.