В прошлой части мы познакомились с отображениями, в этой части мы будем расширять классы Controller, что позволит нам создавать шаблоны для сайтов. Шаблон - обычное отображение которое более или менее базируется на (X)HTML коде. Это позволит содержать наши отображения в рамках DRY или DIE принципа разработки.
Начнём с шаблона страницы. Создадим в каталоге 'application/views' каталог с именем 'templates', запустим наш любимый редактор или IDE и создадим файл со следующим содержимым:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-type" content="text/html; charset=UTF-8" />
<title><?php echo $title;?></title>
<meta name="keywords" content="<?php echo $meta_keywords;?>" />
<meta name="description" content="<?php echo $meta_description;?>" />
<meta name="copyright" content="<?php echo $meta_copywrite;?>" />
<?php foreach($styles as $file => $type) { echo HTML::style($file,array('media' => $type)), "\n"; }?>
<?php foreach($scripts as $file) { echo HTML::script($file), "\n"; }?>
</head>
<body>
<div id="container">
<?php echo $header;?>
<?php echo $content;?>
<?php echo $footer;?>
</div>
</body>
</html>
Сохраним файл под именем 'default.php' в каталоге 'application/views/templates'.
Как вы можете видеть файл шаблона сильно похож на отображения, которые мы создавали ранее (foreach() мы рассмотрим чуть позже), но в отличии от отображения он, скорее всего, будет использоваться во всём вашем проекте. Поскольку мы будем указывать этот файл в качестве шаблона, это уменьшит количество кода который был бы использован в каждом отдельном отображении, что сильно упрощает поддержку проекта.
Итак, у нас есть шаблон, но фреймворк не собирается ничего с ним делать, пока мы не укажем как его использовать. Вернёмся в нашему редактору или IDE и создадим файл 'defaulttemplate.php' в каталоге 'application/classes/controller/' со следующим содержимым:
<?php
defined('SYSPATH') or die('No direct script access.');
class Controller_DefaultTemplate extends Controller_Template
{
public $template = 'templates/default';
/**
* Инициализируем свойства до запуска методов контроллера (actions),
*/
public function before()
{
// Выполняем всё что нужно выполнить до этого
parent::before();
if($this->auto_render)
{
// Инициализируем переменные шаблона с пустыми значениями
$this->template->title = '';
$this->template->meta_keywords = '';
$this->template->meta_description = '';
$this->template->meta_copywrite = '';
$this->template->header = '';
$this->template->content = '';
$this->template->footer = '';
$this->template->styles = array();
$this->template->scripts = array();
}
}
/**
* Заполняем значения по умолчанию для наших свойств перед выводом.
*/
public function after()
{
if($this->auto_render)
{
// Определяем значения по умолчанию
$styles = array('assets/css/reset.css' => 'screen');
$scripts =array('http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js');
// Добавляем значения по умолчанию к переменным шаблона
$this->template->styles = array_reverse(array_merge($this->template->styles, $styles));
$this->template->scripts = array_reverse(array_merge($this->template->scripts, $scripts));
}
// Выполняем всё что нужно выполнить после этого
parent::after();
}
}
Приведённый выше код расширяет контроллер класс 'Controller_Template' и выполняет три основные вещи: инициализирует свойства (переменные) класса и делает их доступными для наших методов, устанавливает значения по умолчанию, затем связывает значения по умолчанию с переменными шаблона перед формированием и выводом шаблона на экран. Тут foreach() цикл в шаблоне вступает в игру. Цикл foreach() использует статические хэлперы-методы класса 'HTML', один для загрузки CSS стилей и ещё один для загрузки JavaScript файлов. Оба этих хелпера-метода обработают массив и упакуют значения в соответствующие тэги, значениями массива могут выступать локальный путь или URL.
Если вы не знакомы с хэлперами, то вам поможет их краткое определение из документации фреймворка Kohana 2
Хэлперы - простые 'подручные' функции которые помогает вам в разработке.
Хэлперы похожи на библиотеки методов, но есть различие. С библиотекой вы должны создавать экземпляр класса библиотеки и использовать его методы. Хэлперы объявлены как статические методы класса, что позволяет их использовать без создания экземпляра класса. Вы можете представлять их как "глобальные функции"
Как и с библиотеками, классы хэлперов автоматически загружаются фреймворком когда они используются, поэтому нет необходимости загружать их самостоятельно.
Немного о Controller_Template.
Абстрактный класс для автоматизации работы с шаблонами, является потомком класса Controller и содержит следующие свойства:
$template - строковый параметр, указывающий на текущий шаблон, по умолчанию 'template'.
$auto_render - логическая переменная, указывающая формировать автоматически страницу или нет, по умолчанию 'TRUE'.
Методы:
before() - загружает файл шаблона.
after() - передаёт сформированный шаблон в качестве ответа на запрос.
Вернёмся к нашему шаблону. Как вы могли заметить есть ссылка на 'assets/css/reset.css'. Давайте рассмотрим этот момент. В DocementRoot нашего проекта создадим каталог 'assets' и в нём создадим ещё один каталог 'css'. Сохраним 'reset.css' от Эрика Майера в каталоге 'assets/css'. Вы можете создать в каталоге assets подкаталоги 'images', 'js' или 'files' для упорядочения статических файлов вашего проекта.
На данный момент наше приложение всё ещё не знает, что делать с тем что мы сделали. Нам нужно изменить наш контроллер. Откроем 'application/classes/controller/first.php'. Мы хотим изменить класс предок нашего контроллера, заменим следующие строки:
class Controller_First extends Controller
на:
class Controller_First extends Controller_DefaultTemplate
Также на необходимо изменить наш метод action_index(), приведя его к следующему виду:
public function action_index()
{
$first_inner = array();
$first = array();
$this->template->title = 'Kohana 3';
View::set_global('x', 'Это глобальная переменная');
$first_inner['content'] = 'У нас есть ещё данные';
$first['content'] = 'У нас есть данные!';
$first['first_inner'] = View::factory('blocks/first_inner', $first_inner)
->render();
$this->template->content= View::factory('pages/first', $first);
}
Сохраним его. Вы можете заметить, что у нас появилась новая строка "$this->template->title = 'Kohana 3'", здесь мы присваиваем значение переменной шаблона 'title'. Следующее, на что вы могли обратить внимание - отсутствие 'render()' метода. Теперь в нём нет необходимости, поскольку 'factory()' метода автоматически формирует в нашем шаблоне переменную 'content'.
Есть ещё одна вещь которую нужно сделать перед загрузкой страницы в браузере. Откроем в редакторе наше отображение 'first.php' расположенное в 'application/views/pages/' и удалив лишний код приведём его к следующему виду:
<h1>Это моё первое отображение</h1> <?php echo $content; ?> <br/><?php echo $x;?> <?php echo $first_inner; ?>
Если вы загрузите страницу в браузере, то увидите, что она имеет заголовок 'Kohana 3' и выглядит практически как в прошлой части, но код страницы выглядит совершенно по другому. Возможно вы удивлены, что мы не используем другие переменные нашего шаблона, давайте это исправим. Изменим action_index() ещё раз:
public function action_index()
{
$first_inner = array();
$first = array();
$this->template->title = "Kohana 3";
$this->template->meta_keywords = 'PHP, Kohana, KO3, Framework';
$this->template->meta_description = 'A test of of the KO3 framework';
$this->template->styles = array('assets/css/red.css' => 'screen');
$this->template->scripts = array('assets/js/jqtest.js');
View::set_global('x', 'Это глобальная переменная');
$first_inner['content'] = 'У нас есть ещё данные';
$first['content'] = 'У нас есть данные!';
$first['first_inner'] = View::factory('blocks/first_inner', $first_inner)
->render();
$this->template->content= View::factory('pages/first', $first);
}
Всё довольно просто. Вы заметили, что не заполнены header и footer? Я уверен, вы знаете, что с ними делать.
Подсказка: сформировать отображение в эту переменную. :) Ещё вы должны заметить, что я добавил 'assets/css/red.css' и 'assets/css/jqtest.js'. Давайте создадим эти файлы, начнём с 'assets/css/red.css':
h1
{
color: #FF0000;
}
Следующий 'assets/js/jqtest.js':
$("document").ready(function()
{
alert('Привет Kohana!');
});
Сохраним их и обновим страницу в браузере. Вы должны увидеть всплывающее окно с предупреждением и первая строка текста стала красной.
Сегодня мы создали файл шаблона, расширили контроллер шаблона и наш контроллер использовал этот шаблон. У того что мы сегодня сделали большой потенциал.
Файлы этого руководства находятся здесь. Так же их можно получить с помощью Subversion :
svn checkout http://dev-mark.googlecode.com/svn/trunk/dev-mark/Kohana3-tutorial/tutorial_03 Kohana3-tutorial-03
В следующий раз мы будем работать с моделями.
P.S. За основу взяты материалы с Inside DealTaker и Unofficial Kohana 3.0 Wiki
Другие части руководства:
- Kohana 3: Установка под Ubuntu
- Kohana 3: Первые шаги (Установка и настройка)
- Kohana 3: Работа с отображениями
- Kohana 3: Работа с контроллерами
- Kohana 3: Работа с моделью

6 комментариев:
Спасибо за подробное руководство! Как раз разбираюсь с Kohana 3, и пока не прочитал, никак не мог понять, как связать базовый шаблон с контроллерами.
Только один вопрос: вместо того, чтобы создавать Controller_DefaultTemplate разве нельзя "перегрузить" непосредственно контроллер Controller_Template?
Всё зависит от задачи которую нужно решить.
Если у каждого контроллера свой уникальный шаблон, то да, лучшим вариантом будет наследовать Controller_Template и уже от него плясать.
Но, если у нас имеется общий шаблон для всего сайта и соответственно всех контроллеров, то удобнее создать класс-прослойку который будет подключать шаблон и обрабатывать методы before() и after(), а его потомкам остается только передавать данные в переменные шаблона.
В этом уроке все получилось за исключением применения CSS и JS. Стиль к заголовку не применяется и предупреждения тоже нет. Подозрения на настройки .htaccess т.к. по ссылкам из сформированного HTML открыть эти файлы тоже не получается.
Какую ошибку пишет в логах apache?
Какие ссылки генерируются?
Какой путь к файлам CSS и JS относительно DocumentRoot apache?
Если у вас linux, то имена файлов и каталогов должны быть в нижнем регистре и открыт доступ к файлам на чтение для всех.
Должны сформироваться такие ссылки:
<link type="text/css" href="/assets/css/reset.css" rel="stylesheet" media="screen" />
<link type="text/css" href="/assets/css/red.css" rel="stylesheet" media="screen" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript" src="/assets/js/jqtest.js"></script>
Возможно проблема с размещением файлов.
Если к адресам сформированных ссылок добавить путь из DocumentRoot настроек сайта, то получим путь к файлам в системе.
Например у меня под WinXP у виртуального хоста DocumentRoot c:/xampp/vhosts/kohana/webroot
Соответственно файл /assets/css/red.css расположен c:/xampp/vhosts/kohana/webroot/assets/css/red.css
Проверьте соответствует ли у вас физическое расположение файлов в системе относительному у вашего сайта (DocumentRoot + Link)
ошибке в логах нет, только в access.log пишет 404.
физически файл лежит в /www/application/asset/css/red.css
DocumentRoot = c:/apache/front.local/www
Все возможные пути изменял, где может быть ошибка?
У вас red.css должен физически распологаться в c:/apache/front.local/www/assets/css/red.css
Путь к нему в браузере http://имя_вашего_хоста/assets/css/red.css
Отправить комментарий