В прошлой части мы познакомились с отображениями, в этой части мы будем расширять классы 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
Отправить комментарий