Создание шаблонов в веб-приложениях крайне важно для отделения вашей бизнес-логики от презентации. Существует два типа шаблонов: шаблоны на стороне сервера, которые используются через механизм шаблонов на стороне сервера во время начальной загрузки страницы, и шаблоны на стороне клиента, которые используются для работы с приложениями на основе JavaScript или запросами Ajax.
В сценариях, где ваше веб-приложение сильно зависит от Ajax, может быть сложно поддерживать как серверные, так и клиентские шаблоны без дублирования. Следовательно, может быть полезно выбрать шаблонизатор, который обеспечивает как клиентскую, так и серверную поддержку, что обеспечивает максимальное повторное использование.
Усы быстро становятся одним из самых популярных шаблонизаторов среди доступных и предоставляют реализации для разных языков программирования и платформ, чтобы удовлетворить наши потребности.
В моей статье Создание шаблонов HTML с Mustache.js на JSPro я показал вам, как работать с шаблонами Mustache в клиентском коде. Если у вас нет опыта работы с усами, я рекомендую прочитать его. В этой статье я сосредоточусь на создании шаблонов усов на стороне сервера и совместном использовании одного и того же набора шаблонов с клиентским JavaScript.
Введение в Mustache.php
Реализация Mustache в PHP называется Mustache.php, и вы можете получить копию библиотеки, используя официальную страницу проекта GitHub . Однако, если вы знакомы с использованием Composer, я рекомендую вам установить Mustache, используя его для лучшего управления зависимостями (а если вы не знакомы с Composer, я рекомендую вам прочитать PHP Dependency Management с Composer ).
Добавьте следующее в файл composer.json
и запустите либо composer install
composer update
либо composer update
(в зависимости от того, что подходит):
{ "require": { "mustache/mustache": "2.0.*" } }
Давайте начнем с простого примера создания шаблонов с Mustache.php.
<?php require 'vendor/autoload.php'; $tpl = new Mustache_Engine(); echo $tpl->render('Hello, {{planet}}!', array('planet' => 'World'));
Сначала включается автозагрузчик Composer (в качестве альтернативы вы можете использовать автозагрузчик Mustache, если вы работаете с клонированной или загруженной копией библиотеки). Затем вызывается метод render()
класса Mustache_Engine
для генерации представления путем передачи ему данных шаблона и некоторых значений замены.
В идеале вы не должны предоставлять содержимое шаблона встроенным, как в примере. Шаблоны должны храниться в своих собственных файлах в специальном каталоге. Вы можете настроить путь к файлам шаблона при создании экземпляра класса Mustache_Engine
.
<?php $mustache = new Mustache_Engine(array( 'loader' => new Mustache_Loader_FilesystemLoader('../templates') )); $tpl = $mustache->loadTemplate('greeting'); echo $tpl->render(array('planet' => 'World'));
Загрузчик в массиве конфигурации определяет путь к файлам шаблона (более подробную информацию о параметрах конфигурации можно найти в вики Mustache.php ). В этом случае файлы шаблонов находятся внутри каталога шаблонов. Метод loadTemplate()
загружает файл templates/greeting.mustache
loadTemplate()
.
Кратко рассмотрев необходимую теорию для работы с усами, теперь мы можем посмотреть, как делиться шаблонами.
Совместное использование шаблонов между PHP и JavaScript
Наша главная цель — разделить шаблоны между PHP (на стороне сервера) и JavaScript (на стороне клиента). В качестве основы для нашего примера давайте предположим, что у нас есть сайт электронной коммерции с двумя категориями продуктов: книги и фильмы. При первом посещении пользователя все продукты будут отображаться в одном списке, как показано ниже.
Вы можете видеть, что детали каждого типа продукта различны; следовательно, нам нужны отдельные шаблоны для двух категорий.
Создайте два шаблона: один называется books.mustache
а другой movies.mustache
. Вот как будет выглядеть файл books.mustache
:
{{#products}} {{#book}} <div> <p>Book Title: {{title}}</p> <p>Book Author: {{author}}</p> <p>Book Price: {{price}}</p> </div> {{/book}} {{/products}}
Выше приведен простой шаблон с разделом для циклических целей и некоторыми специфичными для шаблона переменными. {{#products}}
используется для циклического прохождения всех элементов внутри раздела products в массиве, который мы предоставим. {{#book}}
используется для проверки того, является ли предмет книгой. Если ключ книги не существует, то пользователю ничего не будет отображаться.
При начальной загрузке страницы все продукты должны быть извлечены и отображены пользователю, поэтому мы используем PHP для генерации начального отображения, используя как шаблон, так и набор данных.
<?php $books = array(); $result = $db->query('SELECT title, author, price FROM books'); while ($row = $result->fetch(PDO::FETCH_ASSOC)) { $row['book'] = true; $books[] = $row; } $result->closeCursor(); $movies = array(); $result = $db->query('SELECT name, price, cast FROM movies'); while ($row = $result->fetch(PDO::FETCH_ASSOC)) { $row['movie'] = true; $movies[] = $row; } $booksTmpl = $this->mustache->loadTemplate('books'); $moviesTmpl = $this->mustache->loadTemplate('movies'); $data = array( 'products' => array_merge($books, $movies) ); $html = $booksTmpl->render($data); $html .= $moviesTmpl->render($data); echo $html;
Мы используем два запроса к базе данных, чтобы извлечь данные книги и фильма из базы данных и сохранить их в ассоциативном массиве для передачи в шаблоны. Я использовал основные методы PDO для извлечения данных; Вы можете использовать свой собственный уровень абстракции базы данных или ORM, если хотите.
Шаблоны для книг и фильмов загружаются отдельно в две переменные с помощью loadTemplate()
, и я loadTemplate()
массив products в метод render()
каждого шаблона. Он применяет шаблон к данным продукта и возвращает вывод HTML.
Чтобы отфильтровать результаты по типу продукта, мы могли бы получить все отфильтрованные книги (или фильмы) в формате HTML с сервера, но вся разметка повлекла бы за собой дополнительные издержки для каждого запроса. Мы действительно не хотим посылать одну и ту же разметку снова и снова. Именно здесь вступают в игру шаблоны на стороне клиента — мы можем сохранять необходимые шаблоны загруженными в память на клиенте и загружать данные только с сервера, используя Ajax.
Чтобы сделать шаблоны доступными для клиента, они могут быть вставлены в начальный запрос страницы в тегах <script>
для будущего использования JavaScript. Код внутри этих тегов не будет отображаться, и они не будут выполняться JavaScript, если мы установили тип text/mustache
.
<script id="booksTmpl" type="text/mustache"> <?php echo file_get_contents(dirname(__FILE__) . '/templates/books.mustache'); ?> </script> <script id="moviesTmpl" type="text/mustache"> <?php echo file_get_contents(dirname(__FILE__) . '/templates/movies.mustache');?> </script>
Чтобы использовать эти шаблоны в JavaScript, нам просто нужно включить библиотеку Mustache.js в документ. Вы можете получить копию файла mustache.js со страницы GitHub и включить его в свой HTML-код следующим образом:
<script type="text/javascript" src="mustache.js"></script>
Как только пользователь выберет опцию фильтра, мы можем получить данные, используя запрос Ajax. Но, в отличие от начальной загрузки страницы, мы не будем применять шаблоны к данным до их отправки клиенту, поскольку у нас уже есть шаблоны, доступные на стороне клиента.
<script> $("#booksFilter").click(function () { $.ajax({ type: "GET", url: "ajax.php?type=books" }).done(function (msg) { var template = $("#booksTmpl").html(); var output = Mustache.render(template, msg); $("#products").html(output); }); }); </script>
Список книг извлекается из базы данных и возвращается клиенту в формате JSON, а затем мы извлекаем шаблон книги из тега сценария, используя $("#booksTmpl").html()
и передаем и шаблон, и данные в Функция рендеринга усов на стороне клиента. Сгенерированный вывод затем применяется к разделу продуктов на странице.
Резюме
Работа с отдельными механизмами шаблонов, как на стороне клиента, так и на стороне сервера, может быть сложной задачей и может привести к дублированию шаблона. К счастью, различные реализации Mustache позволяют нам использовать одни и те же шаблоны для обеих сторон. Это повышает удобство сопровождения вашего кода. Если вы хотите поиграть с примером кода для этой статьи, вы можете найти его в учетной записи PHPMaster GitHub .
Не стесняйтесь делиться своими предложениями и опытом работы с шаблонами усов в комментариях ниже.
Изображение через Fotolia