fenom/docs/ru/ext/extend.md
2015-03-08 11:17:14 +05:00

211 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Расширение Fenom
================
# Добавление тегов
В шаблонизаторе принято различать два типа тегов: омпиляторы_ и ункции_.
Компиляторы вызываются во время преобразования кода шаблона в PHP код и возвращяют PHP код который будет вставлен вместо тега.
А функции вызываются непременно в момент выполнения шаблона и возвращают непосредственно данные которые будут отображены.
Среди тегов как и в HTML есть строчные и блоковые теги.
## Линейные функции
Примитивное добавление функции можно осуществить следующим образом:
```php
$fenom->addFunction(string $function_name, callable $callback[, callable $parser]);
```
В данном случае запускается стандартный парсер, который автоматически разберет аргументы тега, которые должны быть в формате HTML атрибутов и отдаст их в функцию ассоциативным массивом:
```php
$fenom->addFunction("some_function", function (array $params) { /* ... */ });
```
При необходимости можно переопределить парсер на произвольный:
```php
$fenom->addFunction("some_function", $some_function, function (Fenom\Tokenizer $tokenizer, Fenom\Template $template) { /* parse tag */});
```
Существует более простой способ добавления произвольной функции:
```php
$fenom->addFunctionSmarty(string $function_name, callable $callback);
```
В данном случае парсер сканирует список аргументов коллбека и попробует сопоставить с аргументами тега.
```php
// ... class XYCalcs ..
public static function calc($x, $y = 5) { /* ... */}
// ...
$fenom->addFunctionSmart('calc', 'XYCalcs::calc');
```
пример выше позволяет объявить тег `{calc}` и спользовать его:
```smarty
{calc x=$top y=50} или {calc y=50 x=$top} вызовет XYCalcs::calc($top, 50)
{calc x=$top} или {calc $top} вызовет XYCalcs::calc($top)
```
Таким образом вы успешно можете добавлять Ваши функции или методы.
## Блоковые функции
Добавление блоковой функции аналогичен добавлению строковой за исключением того что есть возможность указать парсер для закрывающего тега.
```php
$fenom->addBlockFunction(string $function_name, callable $callback[, callable $parser_open[, callable $parser_close]]);
```
Сам коллбек принимает первым аргументом контент между открывающим и закрывающим тегом, а вторым аргументом - ассоциативный массив из аргуметов тега:
```php
$fenom->addBlockFunction('some_block_function', function (array $params, $content) { /* ... */});
```
## Линейный компилятор
Добавление строчного компилятора осуществляеться очень просто:
```php
$fenom->addCompiler(string $compiler, callable $parser);
```
Парсер должен принимать `Fenom\Tokenizer $tokenizer`, `Fenom\Template $template` и возвращать PHP код.
Компилятор так же можно импортировать из класса автоматически
```php
$fenom->addCompilerSmart(string $compiler, $storage);
```
`$storage` может быть как классом так и объектом. В данном случае шаблонизатор будет искать метод `tag{$compiler}`, который будет взят в качестве парсера тега.
## Блоковый компилятор
Добавление блочного компилятора осуществяется двумя способами. Первый
```php
$fenom->addBlockCompiler(string $compiler, array $parsers, array $tags);
```
где `$parser` ассоциативный массив `["open" => parser, "close" => parser]`, сождержащий парсер на открывающий и на закрывающий тег, а `$tags` содержит список внутренних тегов в формате `["tag_name"] => parser`, которые могут быть использованы только с этим компилятором.
Второй способ добавления парсера через импортирование из класса или объекта методов:
```php
$fenom->addBlockCompilerSmart(string $compiler, $storage, array $tags, array $floats);
```
# Добавление модификаторов
```
$fenom->addModifier(string $modifier, callable $callback);
```
* `$modifier` - название модификатора, которое будет использоваться в шаблоне
* `$callback` - коллбек, который будет вызван для изменения данных
Например:
```smarty
{$variable|my_modifier:$param1:$param2}
```
```php
$fenom->addModifier('my_modifier', function ($variable, $param1, $param2) {
// ...
});
```
# Расширение тестового оператора
```php
$fenom->addTest(string $name, string $code);
```
`$code` - PHP код для условия, с маркером для замены на значение или переменную.
Например, тест на целое число `is int` можно добавить как `$fenom->addTest('int', 'is_int(%s)')`.
В шаблоне тесты выглядит как `{$a is int}`, а после компиляции выглядит приблизительно так - `is_int($a)`.
# Расширение глобальной переменной или функции
Fenom обладает определенным набором глобальных переменных и функций. Однако их может не хватать для удобной работы с шаблонами.
В этом случае потребуется добавить, переопределить или удалить существующие глобальные переменные или функции.
Метод `Fenom::addAccessor(string $name, callable $parser)` позволяет добавить свой обработчик на не известную глобальную переменную или функцию.
```php
$fenom->addAccessor('project', function (Fenom\Tokenizer $tokens) { /* code */ });
```
Указанный вторым аргументом, парсер будет вызван при встречи компилятором конструкции `{$.project}`.
Парсеры вызываются только на момент сборки шаблона, а не во время его выполенения.
Через метод `Fenom::addAccessor($name, $parser)` можно переопределить уже любую другую существующую глобальную переменную или функцию.
Метод `Fenom::removeAccessor($name)` позволяет удалить любую определенную глобальную переменную или функцию по ее имени.
# Источники шаблонов
Шаблоны можно получать из самых разных источников.
Когда вы отображаете или вызываете шаблон, либо когда вы подключаете один шаблон к другому, вы указываете источник,
вместе с соответствующим путём и названием шаблона. Если источник явно не задан, то используется источник `Fenom\Provider`,
который считывает шаблоны из указанной директории.
Источник шаблонов должен реализовать интерфейс `Fenom\ProviderInterface`.
Используйте метод `$fenom->setProvider(...)` что бы добавить источник в шаблонизатор, указав название источника и, если есть необходимость,
задать директорию кеша для шаблонов из этого источника. Рассмотрим на примере, реализуем источник шаблонов из базы данных.
Создадим источник:
```php
class DbProvider implements Fenom\ProviderInterface {
// ...
}
```
Добавляем источник, указав удобное имя.
```php
$provider = new DbProvider();
$fenom->setProvider("db", $provider, "/tmp/cached/db");
```
Теперь источник можно использовать.
```php
$fenom->display("db:index.tpl", $vars);
```
```smarty
{include "db:menu.tpl"}
```
# Расширение кеша (эксперементальное)
Изначально Fenom не рассчитывался на то что кеш скомпиленых шаблонов может располагаться не на файловой системе.
Однако, в теории, есть возможность реализовать свое кеширование для скомпиленых шаблонов без переопределения шаблонизатора.
Речь идет о своем протоколе, отличным от `file://`, который [можно определить](http://php.net/manual/en/class.streamwrapper.php) в PHP.
Ваш протокол должен иметь класс реализации как указано в документации [Stream Wrapper](http://www.php.net/manual/en/class.streamwrapper.php).
Класс протокола может иметь не все указанные в документации методы. Вот список методов, необходимых шаблонизатору:
* [CacheStreamWrapper::stream_open](http://www.php.net/manual/en/streamwrapper.stream-open.php)
* [CacheStreamWrapper::stream_write](http://www.php.net/manual/en/streamwrapper.stream-write.php)
* [CacheStreamWrapper::stream_close](http://www.php.net/manual/en/streamwrapper.stream-close.php)
* [CacheStreamWrapper::rename](http://www.php.net/manual/en/streamwrapper.rename.php)
Для работы через `include`:
* [CacheStreamWrapper::stream_stat](http://www.php.net/manual/en/streamwrapper.stream-stat.php)
* [CacheStreamWrapper::stream_read](http://www.php.net/manual/en/streamwrapper.stream-read.php)
* [CacheStreamWrapper::stream_eof](http://www.php.net/manual/en/streamwrapper.stream-eof.php)
**Note**
(On 2014-05-13) Zend OpCacher кроме `file://` и `phar://` не поддерживает другие протоколы.
Пример работы кеша
```php
$this->setCacheDir("redis://hash/compiled/");
```
* `$cache = fopen("redis://hash/compiled/XnsbfeDnrd.php", "w");`
* `fwrite($cache, "... <template content> ...");`
* `fclose($cache);`
* `rename("redis://hash/compiled/XnsbfeDnrd.php", "redis://hash/compiled/main.php");`