Статьи

Введение в шаблонную среду Smarty

Smarty — это движок / фреймворк на основе PHP. Это позволяет дополнительно отделить бизнес-логику от ее визуализации, удалив как можно больше кода PHP из ваших представлений. Некоторые разработчики и фреймворки предпочитают не использовать шаблонизатор, другие предпочитают использовать простой PHP в ваших представлениях. Обе точки зрения могут быть спорными, и, в конце концов, это в основном дело вкуса. Во всяком случае, это никогда не плохая идея, прежде чем принять решение не использовать его, и это то, о чем этот учебник: попробовать Smarty Templating Framework.


В конце этого урока вы узнаете, как работает Smarty . Вы сможете загружать файлы шаблонов, передавать им переменные, использовать «макет», в который вставляются другие ваши представления, и писать свои собственные модификаторы. Все это будет достигнуто с помощью дополнительного класса-оболочки, который вы можете легко интегрировать в существующие проекты.


Проект для этого урока будет очень прост в настройке, так как мы не разрабатываем настоящее приложение. Просто создайте папку проекта (моя называется smarty_example) с файлом index.php в нем и директорией с именем lib внутри нее. Также создайте файл с именем smtemplate.php в папке «lib». Затем создайте папку «views» внутри «smarty_example». Эта папка будет содержать наши файлы шаблонов smarty.

Прежде чем вы сможете что-то использовать, вы должны установить это. К счастью, установка Smarty чрезвычайно проста и практически не требует настройки. Прежде всего, скачайте Smarty и распакуйте архив. Вы можете проверить все внутри архива, но для нашего приложения нам понадобится только папка «libs». Переименуйте его в «smarty» и вставьте в папку «lib» нашего приложения. Smarty использует несколько дополнительных папок, поэтому создайте папки «templates_c», «cache» и «config» внутри нашей папки «lib / smarty». Если вы не используете Windows, вам придется предоставить 775 разрешений на эти папки вашему веб-серверу. Ваше дерево каталогов теперь должно выглядеть так:


У каждого программиста есть свое представление об идеальном API. Чтобы немного изменить API Smarty и позволить нам добавить некоторые дополнительные функциональные возможности, мы создадим класс-оболочку SMTemplate, который позаботится о деталях smarty для нас. У этого подхода есть еще одно преимущество: если в какой-то момент вы решите использовать другой механизм шаблонов, вы можете создать оболочку для этого механизма, сохранив интерфейс SMTemplate и, таким образом, не нарушая код, который использует наш класс SMTemplate.

Перед написанием кода функциональности класса SMTemplate нам понадобится место для хранения некоторых деталей конфигурации. Это можно сделать несколькими способами, например, определив параметры конфигурации как константы класса, определив их как константы в файле smtemplate.php или сохранив их в отдельном файле конфигурации. Я предпочитаю последний вариант, поэтому я создам файл smtemplate_config.php. Smarty требуется настройка для шаблона, скомпилированного шаблона, кеша и каталогов конфигурации. Позже мы могли бы также добавить специфические опции SMTemplate в наш конфигурационный файл, но сейчас это будет сделано:

01
02
03
04
05
06
07
08
09
10
11
12
/**
 * @file
 * Configuration file for the SMTemplate class
 */
  
$smtemplate_config =
    array(
        ‘template_dir’ => ‘views/’,
        ‘compile_dir’ => ‘lib/smarty/templates_c/’,
        ‘cache_dir’ => ‘lib/smarty/cache/’,
        ‘configs_dir’ => ‘lib/smarty/configs/’,
        );

Класс SMTemplate загрузит этот файл конфигурации и передаст параметры в Smarty. Прежде чем мы сможем передать параметры, нам понадобится объект класса Smarty. Наш класс SMTemplate может расширять класс Smarty, но я предпочитаю использовать частную переменную экземпляра для хранения объекта Smarty. Пока у нас есть следующее для нашего класса SMTemplate:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
 * @file
 * Wrapper for Smarty Template Engine
 */
 
require_once(‘smarty/Smarty.class.php’);
require_once(‘smtemplate_config.php’);
 
class SMTemplate{
     
    private $_smarty;
     
    function __construct(){
        $this->_smarty = new Smarty();
         
        global $smtemplate_config;
        $this->_smarty->template_dir = $smtemplate_config[‘template_dir’];
        $this->_smarty->compile_dir = $smtemplate_config[‘compile_dir’];
        $this->_smarty->cache_dir = $smtemplate_config[‘cache_dir’];
        $this->_smarty->configs_dir = $smtemplate_config[‘configs_dir’];
    }
}

Как вы можете видеть, наш класс все еще довольно жалок, так как не может ничего визуализировать. Мы решим эту проблему, добавив функцию рендеринга, которая загружает шаблон и отображает его.

1
2
3
function render($template){
    $this->_smarty->display($template . ‘.tpl’);
}

Чтобы что-то отобразить, нам нужно создать файл шаблона, а затем вызвать функцию рендеринга из нашего файла index.php. Файл шаблона будет довольно простым, содержит простую HTML-страницу. Назовите его «home.tpl» и поместите в наш каталог «views».

01
02
03
04
05
06
07
08
09
10
<html>
    <head>
        <meta http-equiv=»Content-type» content=»text/html; charset=utf-8″ />
        <title>Home</title>
        <link rel=»stylesheet» href=»/css/master.css» type=»text/css» media=»screen» title=»no title» charset=»utf-8″ />
    </head>
    <body>
        <p>Hello, World!</p>
    </body>
</html>

Теперь осталось только создать объект SMTemplate и отобразить «home». Откройте index.php, добавьте следующие строки кода и перейдите туда в своем браузере.

1
2
3
4
require_once(‘lib/smtemplate.php’);
 
$tpl = new SMTemplate();
$tpl->render(‘home’);

Если бы мы не могли ничего визуализировать динамически, Smarty был бы довольно бесполезен. К счастью, мы можем назначить переменные нашему классу smarty и отобразить их в нашем шаблоне. Мы также можем использовать некоторые функции Smarty (ну, на самом деле, модификаторы) для их правильного форматирования.

Хотя Smarty поддерживает присваивание переменных, наш SMTemplate не поддерживает (пока). Мы предоставим стиль присвоения CodeIgniter, в котором вы передаете массив функции рендеринга. Вы можете адаптировать SMTemplate для поддержки других методов; например, присвоение их объекту и последующее использование __set для сохранения их в массиве также является чистым способом. Для этого урока, хотя, передача массива подойдет. Перед назначением переменных мы отредактируем наш шаблон на что-то более динамичное. Приветствие всему миру является привычным для программистов, но не очень полезным, поэтому давайте используем переменную, чтобы определить, кто нам привет. Во-вторых, мы добавим сегодняшнюю дату в сообщение. Переменные можно отобразить, заключив их в фигурные скобки.

1
2
3
<body>
    <p>Hello, {$receiver}!
</body>

Если вы обновите страницу, вы увидите, что переменные не были заполнены, поскольку мы их не задавали. Установка переменных может быть выполнена с помощью smarty-> assign, поэтому давайте их назначим. Функция рендера теперь будет принимать необязательный массив данных в качестве второго аргумента.

1
2
3
4
5
6
function render($template, $data = array()){
    foreach($data as $key => $value){
        $this->_smarty->assign($key, $value);
    }
    $this->_smarty->display($template . ‘.tpl’);
}

Это все равно не будет работать, потому что мы не передаем массив при вызове нашей функции рендеринга. Мы можем легко сделать это, изменив несколько строк в нашем файле index.php.

1
2
3
4
5
6
7
$data = array(
    ‘receiver’ => ‘JR’,
    ‘date’ => time(),
    );
 
$tpl = new SMTemplate();
$tpl->render(‘home’, $data);

Если вы обновите сейчас, на странице будет что-то вроде «Здравствуйте, JR! Сегодня 1282810169!». Конечно, эта дата не совсем то, что мы имели в виду. Это должно быть отформатировано, что приводит нас к следующему разделу.

Smarty — это не просто движок шаблонов, который ищет и заменяет переменные. Это также мощная среда, которая позволяет вам экономить время, используя такие вещи, как модификаторы, функции и блоки. Например, если мы хотим отформатировать нашу дату, мы можем использовать модификатор date_format. Чтобы применить модификатор к переменной, просто поместите символ канала и имя модификатора за ним, а затем необязательные аргументы, разделенные двоеточиями. Модификатор date_format принимает строковый аргумент, который представляет формат, который примет дата, и необязательную дату по умолчанию, которая нам не понадобится. Следующий код будет отображать дату как «день (в десятичных числах) месяц».

1
2
3
<body>
    <p>Hello, {$receiver}!
</body>

Теперь это должно дать что-то вроде «Здравствуйте, JR! Сегодня 26 августа!» Теперь, может быть, мы хотим убедиться, что наш приемник в верхнем регистре. Мы можем добиться этого, используя верхний модификатор.

1
2
3
<body>
    <p>Hello, {$receiver|upper}!
</body>

Теперь, если я изменю index.php, чтобы передать «jr» вместо «JR», шаблон все равно будет показывать «JR». Легко, не правда ли? Далее мы включим наши шаблоны в «макет» по умолчанию.


Прежде чем мы изменим наш класс SMTemplate, чтобы включить макеты, мы сначала создадим макет. Создайте новый каталог с именем «layouts» внутри нашей папки «smarty_example» и переместите туда home.tpl. Переименуйте его в «page.tpl». Мы удалим наш предыдущий контент ‘hello world’ и поместим две горизонтальные линии. Наш контент будет помещен между этими строками.

01
02
03
04
05
06
07
08
09
10
11
<html>
    <head>
        <meta http-equiv=»Content-type» content=»text/html; charset=utf-8″ />
        <title>Home</title>
        <link rel=»stylesheet» href=»/css/master.css» type=»text/css» media=»screen» title=»no title» charset=»utf-8″ />
    </head>
    <body>
        <hr />
        <hr />
    </body>
</html>

Конечно, это не поможет, так как Smarty не будет знать, куда вставить наш контент. Существует несколько способов получения содержимого из другого шаблона внутри нашего макета, и я буду использовать функцию извлечения Smarty. Эта функция возвращает наш шаблон в виде текста вместо его отображения. Это означает, что мы можем получить шаблон, а затем назначить его переменной для использования в нашем шаблоне! Имя этой переменной остается на ваше усмотрение. Я ставлю свои специальные переменные перед __, чтобы отличать их от других переменных, которые я использую. Я назову это «контентом», так как мы присваиваем ему контент нашей страницы.

1
2
3
4
5
<body>
    <hr />
        {$__content}
    <hr />
</body>

На этом наш макет завершен, поэтому давайте создадим несколько шаблонов для использования в качестве контента. Я создам шаблон ‘hello’, который будет содержать стандартную строку ‘hello world’, и шаблон ‘lipsum’, который содержит некоторый текст Lorem Ipsum. Не забудьте дать этим шаблонам расширение .tpl.

1
<p>Hello, World!</p>
1
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Адаптация нашего класса SMTemplate для использования макета также чрезвычайно проста. Сначала мы настроим параметр конфигурации для каталога раскладок, как мы сделали для наших представлений.

01
02
03
04
05
06
07
08
09
10
11
12
13
/**
 * @file
 * Configuration file for the SMTemplate class
 */
  
$smtemplate_config =
    array(
        ‘layouts_dir’ => ‘layouts/’,
        ‘template_dir’ => ‘views/’,
        ‘compile_dir’ => ‘lib/smarty/templates_c/’,
        ‘cache_dir’ => ‘lib/smarty/cache/’,
        ‘configs_dir’ => ‘lib/smarty/configs/’,
        );

Далее мы изменим нашу функцию рендеринга. Мы предоставим макет в качестве необязательного третьего параметра и по умолчанию оставим «page». Затем мы извлечем запрошенный шаблон, назначим его переменной содержимого $ __ и отобразим наш макет.

1
2
3
4
5
6
7
8
function render($template, $data = array(), $layout = ‘page’){
    foreach($data as $key => $value){
        $this->_smarty->assign($key, $value);
    }
    $content = $this->_smarty->fetch($template . ‘.tpl’);
    $this->_smarty->assign(‘__content’, $content);
    $this->_smarty->display($layout . ‘.tpl’);
}

Есть несколько вещей, которые следует учитывать в отношении этого кода. Прежде всего, мы еще не сказали Smarty, где найти наши макеты. Мы можем сделать это, добавив шаблон dir, но этот подход означает, что мы не можем дать нашим макетам то же имя, что и наши шаблоны — Smarty не знает, какой из них выбрать. Мы могли бы решить эту проблему, предоставив нашим макетам другое расширение, либо установив и сбросив наш каталог шаблонов внутри нашей функции рендеринга, либо используя более продвинутые функции Smarty. Сейчас мы просто ограничимся тем, что макеты и представления не могут иметь одинаковые имена. Мы можем добавить наш каталог раскладок с помощью функции addTemplateDir ().

01
02
03
04
05
06
07
08
09
10
function __construct(){
    $this->_smarty = new Smarty();
     
    global $smtemplate_config;
    $this->_smarty->template_dir = $smtemplate_config[‘template_dir’];
    $this->_smarty->addTemplateDir($smtemplate_config[‘layouts_dir’]);
    $this->_smarty->compile_dir = $smtemplate_config[‘compile_dir’];
    $this->_smarty->cache_dir = $smtemplate_config[‘cache_dir’];
    $this->_smarty->configs_dir = $smtemplate_config[‘configs_dir’];
}

Давайте проверим это, изменив наш файл index.php снова.

1
2
3
4
require_once(‘lib/smtemplate.php’);
 
$tpl = new SMTemplate();
$tpl->render(‘hello’);

Оно работает!

И если мы изменим его для рендеринга ‘lipsum’, он также будет работать:


В качестве заключительной части этого урока я представлю одну из более продвинутых функций Smarty, которые делают его более простым, чем простой движок шаблонов. Smarty содержит ряд стандартных функций и модификаторов, но также очень легко создавать свои собственные. Давайте посмотрим на модификатор, который мы использовали для форматирования нашей даты:

1
{$date|date_format:»%d %B»}

Если вам нужен пользовательский модификатор, все, что вам нужно сделать, это написать функцию PHP.

Это фактически приведет к вызову функции smarty_modifier_date_format () с $ date и нашей строкой формата в качестве аргументов. Эта функция будет возвращать строку, и эта строка будет отображаться. Поэтому, если вам нужен пользовательский модификатор, все, что вам нужно сделать, это написать функцию PHP. В качестве примера мы напишем модификатор ‘weirdcase’, который будет писать все согласные прописными буквами и все гласные строчные буквы, т.е. Lorem Ipsum становится LoReM IPSuM. Для этого создайте файл с именем «modifier.weirdcase.php» в папке «lib / smarty / plugins». Наш модификатор будет принимать только один аргумент — строку, которую нужно изменить.

01
02
03
04
05
06
07
08
09
10
11
12
13
/**
 * Smarty weirdcase modifier plugin
 *
 * Type: modifier
 * Name: weirdcase
 * Purpose: turn consonants into uppercase and vowels into lowercase
 * @param string
 * @return string
 */
  
function smarty_modifier_weirdcase($string){
 
}

Мы можем получить наш результат, определив массив «гласных», превратив нашу строку в массив, а затем пройдя ее и проверив, присутствует ли каждый символ в нашем массиве гласных. Если это так, мы пишем его строчными буквами, иначе мы пишем его прописными буквами Затем измененные символы добавляются в переменную результата.

01
02
03
04
05
06
07
08
09
10
11
12
function smarty_modifier_weirdcase($string){
    $str_array = str_split($string);
    $result = »;
    $vowels = array(‘a’, ‘e’, ‘i’, ‘o’, ‘u’);
     
    foreach ($str_array as $char){
        if (in_array($vowels, $char)) $result .= strtolower($char);
        else $result .= strtoupper($char);
    }
     
    return $result;
}

Это должно сработать, поэтому давайте проверим это. Отредактируйте шаблон ‘lipsum.tpl’ и добавьте в него h1, содержащий наш странный ‘Lorem Ipsum’.

1
2
<h1>{‘Lorem Ipsum’|weirdcase}</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Хотя в Smarty есть гораздо больше, чем я мог бы уместить в этом уроке, надеюсь, это даст вам базовые знания о том, как с ним работать. По сути, вы уже знаете все, что вам нужно знать. Вы также должны быть в состоянии определить, нравится ли вам идея использования этой структуры шаблонов или нет. Более сложные темы, такие как фильтры и блоки, полезны, однако без них все равно будет хорошо. Вы можете найти документацию по более продвинутым функциям на веб-сайте Smarty . Спасибо за прочтение!