Если серьёзно, то я по всякому прикинул, как заставить наш простенький сайт выводить HTML, и не вписывать его в PHP, а хранить в шаблонах.
Варианта ровно два: написать собственный жуткий глючный велосипед, который будет читать шаблон и заменять в нём плейсхолдеры на значения через str_replace(), или подключить нормальный шаблонизатор.
Так как мы все тут от MODX люди не очень далёкие, так почему бы не освоить работу с Fenom, который в нём с некоторых пор доступен? Думаю, возражений не будет, так что поехали!
Зачем?
Для начала давайте определимся, зачем нам вообще нужен шаблонизатор? Можно же писать HTML прямо в PHP и выводить его через echo?Можно, конечно. Но такой код будет очень сложно развивать и поддерживать, даже если вы работаете над ним в одиночку. А если с вами будет работать еще и дизайнер\верстальщик, то ему придётся выучить PHP и разобраться в вашем коде, чтобы вносить изменения.
Подключение же шаблонизатора позволит очень просто менять внешний вид сайта, используя его синтаксис. Знания PHP не нужны, а код и представление разделены.
Подключение
Идём в репозиторий Fenom и скачиваем свежий релиз.Распаковываем архив и переносим всё из директории scr в нашу Core. Так как Fenom придерживается PSR, то свою директорию называет с большой буквы. Чтобы не ломать единообразие, переименуем и нашу директорию controllers в Controllers.
Заодно порадуемся тому факту, что путь к контроллерам у нас задан в конфиге класса Core под ключом controllersPath — указываем заглавную букву и там. Код на GitHub сейчас такой.
Теперь нам нужно как-то добавить работу с Fenom в наш класс Core. Пишем для этого отдельный метод getFenom():
public function getFenom() { // Работаем только, если переменная класса пуста if (!$this->fenom) { // Пробуем загрузить шаблонизатор // Все выброшенные исключения внутри этого блока будут пойманы в следующем try { // Подключаем класс загрузки if (!class_exists('Fenom')) { require 'Fenom.php'; // Регистрируем остальные классы его методом Fenom::registerAutoload(); } // Проверяем и создаём директорию для кэширования скомпилированных шаблонов if (!file_exists($this->config['cachePath'])) { mkdir($this->config['cachePath']); } // Запускаем Fenom $this->fenom = Fenom::factory($this->config['templatesPath'], $this->config['cachePath'], $this->config['fenomOptions']); } // Ловим исключения, если есть, и отправляем их в лог catch (Exception $e) { $this->log($e->getMessage()); // Возвращаем false return false; } } // Возвращаем объект Fenom return $this->fenom; }Здесь всё по инструкции от автора.
Как видите, загрузка Fenom происходит только один раз, потом Core будет отдавать уже инициализированный экземпляр. Также по коду видно, что добавились и новые параметры в настройки, и метод log(), для вывода ошибок.
Предлагаю всё это посмотреть вам на GitHub, вместе с нашим первым шаблоном в /Core/Templates/home.tpl:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Третий курс обучения на bezumkin.ru</title> </head> <body> <h1>Привет, мир!</h1> </body> </html>Который выводит контроллер Home:
public function run() { // Метод getFenom() может вернуть или false, или объект // Так что нужно проверять, что именно приходит if ($fenom = $this->core->getFenom()) { return $fenom->fetch('home.tpl'); } else { return ''; } }Скелет шаблонизации готов, можно работать дальше.
Шаблоны
Предлагаю теперь нам еще подключить Bootstrap для оформления страниц и нарисовать простейший шаблон, которым будут оформлены главная страница, и test.Качаем последний Bootstrap, распаковывем и кладём в директорию /assets/. Вот состояние нашего репозитория с подключенным Bootstrap.
Дальше предусматриваем в шаблоне переменные Fenom, которые он потом заменит на полученные от контроллера значения:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>{$pagetitle}</title> <link rel="stylesheet" href="/assets/css/bootstrap.min.css"> </head> <body> <div class="container"> <h3>{$longtitle ?: $pagetitle}</h3> {$content} </div> </body> <footer> <script src="/assets/js/jquery-2.1.4.min.js"></script> <script src="/assets/js/bootstrap.min.js"></script> </footer> </html>
После чего в контроллере Home меняем метод run() вот так:
public function run() { if ($fenom = $this->core->getFenom()) { return $fenom->fetch('home.tpl', array( 'pagetitle' => 'Тестовый сайт', 'longtitle' => 'Третий курс обучения', 'content' => 'Текст главной страницы курса обучения на bezumkin.ru', )); } else { return ''; } }
Как видите, наш шаблон уже умеет проверять longtitle на пустоту и подставлять вместо него pagetitle, если нужно. Пользуемся этим в методе run() контроллера Test:
public function run() { if ($fenom = $this->core->getFenom()) { return $fenom->fetch('home.tpl', array( 'pagetitle' => 'Тестовая страница', 'longtitle' => '', 'content' => 'Текст тестовой страницы курса обучения на bezumkin.ru', )); } else { return ''; } }
Вот мы и немного оформили наши две страницы с помощью шаблонов Fenom и Twitter Bootstrap.
Заключение
На следующем уроке мы сильнее погрузимся в шаблонизацию и научимся работать с синтаксисом Fenom.Попробуем вывести панель навигации по сайту, написать отдельный шаблон для страницы Test и выделить общие элементы двух шаблонов в отдельный файл, чтобы не копировать один код (head, footer).
На данный момент наш сайт выглядит вот так.
← Следующая заметка
Расширение и наследование шаблонов Fenom
Расширение и наследование шаблонов Fenom
Предыдущая заметка →
Базовый контроллер и его методы
Базовый контроллер и его методы
Так вот это обращение идёт каждый раз и пересоздаётся папка с кэшем? или при каком-то условии, подгружается из кэша?
Fenom сам кэширует скомпилированные шаблоны, и сам загружает их из своего кэша — у нас об этом голова вообще не болит.
Хоть метод для очистки кэша мы и задали, но пока нигде не используем.
Появилась ошибка на хостинге Nic.ru:
Fatal error: Undefined constant 'T_ABSTRACT' in .../docs/Core/Fenom/Template.php on line 254
На другом хостинге и на локалке всё нормально. Вроде как это вопрос версии php, но перебрал все от 5.2 до 5.6. Расширения тоже перепроверил на всякий случай.
вздохнул… всё перепроверил, сделал заново — не помогло.
Нет ли версий — что это может быть?
Модуль был выключен.
Благодарю!
Так как я новичок, и особенности ООП для меня пока не особо известны — ошибку искал долго.
На Github нашел подсказку Василия — Опечатка в названии метода в файле Controller.php
Оказывается Василий в предыдущих уроках опечатался и написал _construct вместо __construct.
Помню заметил, но подумал «Ему виднее». В итоге метод не срабатывал и экземпляр класса core дальше не передавался.
С другой стороны подобный поиск ошибки заставил меня прогнать весь код в голове заново.
Я потренировался писать свои методы, посмотрел, что срабатывает, а что нет. Так что получилась дополнительная практика.
После этой строки
В классе метод __construct с очепяткой назван (не хватает _ )
почему именно так, а не, условно,
как мы раньше вызывали методы своих классов?
На php.net почитал, но ничего толком не понял. Спасибо.
Такой записью мы вызываем статический элемент без создания экземпляра класса
Пока только непонятно, почему метод registerAutoload создан именно статическим, но думаю ответ появится в процессе дальнейшего чтения документации по этой теме.
Статические методы — это, грубо говоря, обычные функции, которым не нужно обращаться к другим методам или свойствам самого класса. Вернее, обращаться они могут только к таким же статическим методам.