Template Toolkit: Руководство: Конфигурация

Template Toolkit

(русская редакция)

[ Пособия ] [ Руководство ] [ Модули ] [ Библиотеки ] [ Утилиты ] [ Вопросы ] [ Релиз ] [ Perl-ресурсы ] Форум ]
 
Поиск
Template Toolkit | Руководство | Конфигурация

Конфигурация

[ ◄ Виртуальные методы ] [ Фильтры ► ]
Опции конфигурации.

Оглавление

ОПИСАНИЕ

Индекс ] [ Руководство ] [ Наверх ]

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

Стиль шаблонов и опции парсера

  • START_TAG, END_TAG

    Опции START_TAG и END_TAG используются для указания последовательностей символов или регулярных выражений, используемых для обозначения начала и конца директивы шаблона. Значения по умолчанию для START_TAG и END_TAG - '[%' и '%]' соответственно, дают знакомый нам стиль директив:

        [% example %]

    В определении тегов можно использовать любые символы регулярных выражений Perl, поэтому, если планируется использовать эти символы, их нужно экранировать (либо использовать Perl-функцию 'quotemeta').

        my $template = Template->new({
      	START_TAG => quotemeta('<+'),
      	END_TAG   => quotemeta('+>'),
        });

    Пример:

        <+ INCLUDE foobar +>

    Директива TAGS может быть использована для установки значений START_TAG и END_TAG внутри файла шаблона.

        [% TAGS <+ +> %]
  • TAG_STYLE

    Опция TAG_STYLE используется для одновременной установки START_TAG и END_TAG в соответсвие с предопределенными стилями тегов.

        my $template = Template->new({
      	TAG_STYLE => 'star',
        });

    Доступны следующие стили:

        template    [% ... %]               (по умолчанию)
        template1   [% ... %] or %% ... %%  (TT версии 1)
        metatext    %% ... %%               (Text::MetaText)
        star        [* ... *]               (TT альтернативный)
        php         <? ... ?>               (PHP)
        asp         <% ... %>               (ASP)
        mason       <% ...  >               (HTML::Mason)
        html        <!-- ... -->            (HTML комментарии)

    Любые значения, определенные в START_TAG и/или END_TAG, переопределяют соответствующие, определенные с помощью TAG_STYLE.

    Директиву TAGS также можно использовать для установки TAG_STYLE

        [% TAGS html %]
        <!-- INCLUDE header -->
  • PRE_CHOMP, POST_CHOMP

    Все что находится вне тегов директив рассматривается как обычный текст и, в общем случае, пропускается без изменений (исключения описываются в описании опции INTERPOLATE). Этот текст содержит все пробельные символы и символы переноса строки окружающие теги директив. Директивы, которые ничего не выводят, будут оставлять дыры в результирующем документе.

    Пример:

        Foo
        [% a = 10 %]
        Bar

    Вывод:

        Foo
        Bar

    Опции PRE_CHOMP и POST_CHOMP могут помочь в удалении этих ненужных пустот. Обе опции выключены по умолчанию.

        my $template = Template->new({
    	PRE_CHOMP  => 1,
    	POST_CHOMP => 1,
        });

    Если PRE_CHOMP установлена в 1, символ новой строки и пробельные символы, предшествующие директиве от начала строки, будут удалены. Это равносильно подклеиванию строки, начинаемой директивой, к концу предыдущей строки.

     	Foo <----------.
     		       |
        ,---(PRE_CHOMP)----'
        |
        `-- [% a = 10 %] --.
     		       |
        ,---(POST_CHOMP)---'
        |
        `-> Bar

    Если POST_CHOMP установлена в 1, все пустое пространство после директивы до символа новой строки включительно будет удалено. Это равносильно включением строки, завершаемой директивой, в начало следующей строки.

    Если PRE_CHOMP или POST_CHOMP установлены в 2, вместо удаления все пустоты сжимаются в единственный пробел. Это полезно для HTML, в котором (как правило) блок смежных пробельных символов интерпретируется как единичный пробел.

    Вы можете использовать константы CHOMP_NONE, CHOMP_ALL и CHOMP_COLLAPSE из модуля Template::Constants для, соответственно, выключения обрезания, удаления всех пустот или сжатия пустот в пробел.

    PRE_CHOMP и POST_CHOMP можно активировать для директив индивидуально, помещая символ '-' в начале и/или конце директивы.

        [% FOREACH user = userlist %]
           [%- user -%]
        [% END %]

    Символы '-' активируют как PRE_CHOMP так и POST_CHOMP для одной директивы '[%- name -%]'. Таким образом, шаблон будет обработан как, если бы блок был записан в таком виде:

        [% FOREACH user = userlist %][% user %][% END %]

    Учтите, что это аналогично установке PRE_CHOMP и POST_CHOMP в CHOMP_ALL; единственный способ добиться поведения CHOMP_COLLAPSE - это соответствующая установка PRE_CHOMP или POST_CHOMP. Если же PRE_CHOMP или POST_CHOMP уже установлены в CHOMP_COLLAPSE, использование '-' даст эффект CHOMP_COLLAPSE, а не CHOMP_ALL.

    Аналогично символы '+' можно использовать, чтобы запретить опции PRE_CHOMP или POST_CHOMP (т.е. не удалять пустоты/переносы строк) на уровне директивы.

        [% FOREACH user = userlist %]
        User: [% user +%]
        [% END %]

    Если POST_CHOMP разрешена, приведенный выше пример будет обработан, как если бы блок был записан так:

        [% FOREACH user = userlist %]User: [% user %]
        [% END %]
  • TRIM

    Опцию TRIM можно установить, чтобы удалить из вывода всех файлов-шаблонов и блоков BLOCK начальные и конечные пробельные символы.

    Например, следующее определение BLOCK

        [% BLOCK foo %]
        Line 1 of foo
        [% END %]

    будет обработано как "\nLine 1 of foo\n". Когда блок будет включен с помощью INCLUDE, окружающие символы новой строки будут добавлены.

        before
        [% INCLUDE foo %]
        after

    Вывод:

        before
        Line 1 of foo
        after

    При установленной опции TRIM начальные и завершающие символы новой строки (которые считаются пробельными) будут удалены из вывода блока.

        before
        Line 1 of foo
        after

    По умолчанию опция TRIM запрещена (установлена в 0).

  • INTERPOLATE

    Установка флага INTERPOLATE в любое истинное значение приведет к тому, что все ссылки на переменные в тексте, (то есть находящиеся не внутри директив, определяемых START_TAG и END_TAG) будут распознаны и соответствующим образом обработаны.

        my $template = Template->new({
      	INTERPOLATE => 1,
        });

    В качестве признака переменной используется префикс '$'. При необходимости можно использовать фигурные скобки (в знакомом Perl/shell стиле) для явного выделения имен переменных.

        # INTERPOLATE => 0
        <a href="http://[% server %]/[% help %]">
        <img src="[% images %]/help.gif"></a>
        [% myorg.name %]
    
        # INTERPOLATE => 1
        <a href="http://$server/$help">
        <img src="$images/help.gif"></a>
        $myorg.name
    
        # явное указание с помощью {  }
        <img src="$images/${icon.next}.gif">

    Учитывайте ограничение, накладываемое обработчиком регулярных выражений Perl, на максимальный размер обрабатываемого шаблона - около 32 килобайтов или, возможно, меньше. Работа с файлами, которые превышают этот размер обычно приводят к аварийному завершению Perl с ошибкой сегментации. Если вы постоянно обрабатываете шаблоны такого размера, то вам необходимо либо запретить INTERPOLATE либо разбить шаблоны на более мелкие файлы или блоки, которые затем можно будет собрать обратно с помощью PROCESS или INCLUDE.

  • ANYCASE

    По умолчанию, ключевые слова директив должны записываться в ВЕРХНЕМ РЕГИСТРЕ. Установка опции ANYCASE разрешает использование ключевых слов в любом регистре.

        # ANYCASE => 0 (по умолчанию)
        [% INCLUDE foobar %]	# OK
        [% include foobar %]        # ошибка
        [% include = 10   %]        # OK, 'include' - переменная
        # ANYCASE => 1
        [% INCLUDE foobar %]	# OK
        [% include foobar %]	# OK
        [% include = 10   %]        # ошибка, 'include' - зарезервированное слово

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

        GET CALL SET DEFAULT INSERT INCLUDE PROCESS WRAPPER
        IF UNLESS ELSE ELSIF FOR FOREACH WHILE SWITCH CASE
        USE PLUGIN FILTER MACRO PERL RAWPERL BLOCK META
        TRY THROW CATCH FINAL NEXT LAST BREAK RETURN STOP
        CLEAR TO STEP AND OR NOT MOD DIV END

    Единственные зарезервированные слова в нижнем регистре, которые нельзя использовать в качестве имен переменных вне зависимости от установки ANYCASE, это операторы:

        and or not mod div

Файлы шаблонов и блоки

  • INCLUDE_PATH

    INCLUDE_PATH используется для указания одного или нескольких каталогов, в которых расположены файлы шаблонов. Когда запрашивается шаблон, который не определен локально с помощью директивы BLOCK, каждый из каталогов, определенных в INCLUDE_PATH, просматривается в поисках файла-шаблона. Несколько каталогов можно указать с помощью ссылки на массив или в виде одной строки, в которой каталоги разделены символом ':'.

        my $template = Template->new({
            INCLUDE_PATH => '/usr/local/templates',
        });
    
        my $template = Template->new({
            INCLUDE_PATH => '/usr/local/templates:/tmp/my/templates',
        });
    
        my $template = Template->new({
            INCLUDE_PATH => [ '/usr/local/templates',
                              '/tmp/my/templates' ],
        });

    В системах Win32, используется небольшой дополнительный трюк - игнорируются разделители ':', за которыми сразу следуют символы '/' или '\'. Это позволяет избежать путаницы при использовании каталогов с такими именами 'C:\Blah Blah'.

    При использовании массива для определения каталогов, INCLUDE_PATH может содержать элементы, которые динамически генерируют список каталогов для INCLUDE_PATH. Эти элементы-генераторы можно определить как ссылки на функции или объекты с методом paths().

        my $template = Template->new({
            INCLUDE_PATH => [ '/usr/local/templates',
                              \&incpath_generator,
    			  My::IncPath::Generator->new( ... ) ],
        });

    При каждом запросе шаблона и проверке INCLUDE_PATH, будет вызываться функция или метод объекта, которые должны вернуть ссылку на массив с путями к каталогам. При возникновении ошибки функции-генераторы должны вызывать die() с сообщением о причине ошибки. Методы-генераторы в этом случае должны вернуть undef, а причина ошибки должна возвращаться через вызов метода error() объекта.

    Например:

        sub incpath_generator {
    	# ...код...
    
    	if ($all_is_well) {
    	    return \@list_of_directories;
    	}
    	else {
    	    die "cannot generate INCLUDE_PATH...\n";
    	}
        }

    или:

        package My::IncPath::Generator;
        # Template::Base (или Class::Base) предоставляет метод error()
        use Template::Base;
        use base qw( Template::Base );
        sub paths {
    	my $self = shift;
    	# ...код...
            if ($all_is_well) {
    	    return \@list_of_directories;
    	}
    	else {
    	    return $self->error("cannot generate INCLUDE_PATH...\n");
    	}
        }
        1;
  • DELIMITER

    Используется для установки альтернативной последовательности символов, используемой для разделения путей, заданных в INCLUDE_PATH. Значение по умолчанию для DELIMITER - ':'.

        # позволим использовать соглашения файловой системы глупого Билли (Silly Billy)
        my $template = Template->new({
    	DELIMITER    => '; ',
            INCLUDE_PATH => 'C:/HERE/NOW; D:/THERE/THEN',
        });
        # решение получше: установите Linux!  :-)

    На системах Win32, разделитель по умолчанию используется немного более разумно, разбивая пути только по символам ':', за которыми нет сразу символа '/'. Это означает, что следующий пример будет работать как и запланировано, разделяя INCLUDE_PATH на 2 каталога C:/foo и C:/bar.

        # только для Win32
        my $template = Template->new({
    	INCLUDE_PATH => 'C:/Foo:C:/Bar'
        });

    Тем не менее, при использовании Win32 рекомендуется явно переопределить символ DELIMITER на что-нибудь иное (например, ';'), а не полагаться на этот тонкий трюк.

  • ABSOLUTE

    Флаг ABSOLUTE указывает, можно ли загружать шаблоны с абсолютными путями (например, '/foo/bar'). Опция запрещена по умолчанию и любая попытка загрузить шаблон с таким именем приведет к возбуждению исключения 'file'.

        my $template = Template->new({
    	ABSOLUTE => 1,
        });
        # именно поэтому опция запрещена по умолчанию
        [% INSERT /etc/passwd %]

    Для Win32 систем регулярное выражение для проверки абсолютных путей немного подправлено, чтобы также определять имена, которые начинаются с буквы устройства и двоеточия, например:

        C:/Foo/Bar
  • RELATIVE

    Флаг RELATIVE указывает, можно ли загружать шаблоны с относительными относительно текущего каталога путями (например, './foo/bar' или '../../some/where/else'). Эта опция также запрещена по умолчанию, и в случае обнаружения таких имен файлов шаблонов, будет возбуждено исключение 'file'.

        my $template = Template->new({
    	RELATIVE => 1,
        });
        [% INCLUDE ../logs/error.log %]
  • DEFAULT

    С помощью опции DEFAULT можно указать шаблон по умолчанию, который будет использован, если указанный шаблон не будет найден в INCLUDE_PATH.

        my $template = Template->new({
    	DEFAULT => 'notfound.html',
        });

    Если запрашивается несуществующий шаблон через метод Template process() или через директивы INCLUDE, PROCESS или WRAPPER, то вместо него будет обработан шаблон DEFAULT в случае, если он определен. Имейте в виду, что шаблон DEFAULT не используется, когда шаблоны указаны с абсолютными или относительными путями, или если он определен как указатель на входной файл или текстовая строка.

  • BLOCKS

    Опция BLOCKS используется для предварительного определения набора шаблонов-блоков по умолчанию. Они должны быть указаны как ссылка на хэш, связывающий имена шаблонов и текст шаблонов, функции или объекты Template::Document.

        my $template = Template->new({
    	BLOCKS => {
    	    header  => 'The Header.  [% title %]',
    	    footer  => sub { return $some_output_text },
    	    another => Template::Document->new({ ... }),
    	},
        }); 
  • AUTO_RESET

    Опция AUTO_RESET установлена по умолчанию и вызывает очистку кэша локальных блоков (BLOCK) объекта Template::Context при каждом вызове метода Template process(). Это гарантирует, что любой блок определенный внутри шаблона будет существовать только во время обработки этого шаблона. Это предотвращает возможность влияния блоков, определенных при одном запросе на обработку шаблона, на последующие независимые запросы к тому же объекту Template::Context.

    Опция BLOCKS может использоваться для определения набора блоков по умолчанию для объекта Template::Context. Последующие определения BLOCK в шаблонах переопределят их, но они будут восстанавливаться при каждом сбросе, если AUTO_RESET разрешена (по умолчанию), или после вызова метода reset() объекта Template::Context.

  • RECURSION

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

Переменные шаблона

  • VARIABLES, PRE_DEFINE

    Опция VARIABLES (или PRE_DEFINE - они эквивалентны) используется для определения хэша переменных шаблона, который будет использован для предварительной инициализации хранилища переменных при его создании. Эти элементы игнорируются, если определена опция STASH.

        my $template = Template->new({
    	VARIABLES => {
    	    title   => 'A Demo Page',
    	    author  => 'Joe Random Hacker',
    	    version => 3.14,
    	},
        };

    или

        my $template = Template->new({
    	PRE_DEFINE => {
    	    title   => 'A Demo Page',
    	    author  => 'Joe Random Hacker',
    	    version => 3.14,
    	},
        };
  • CONSTANTS

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

        my $template = Template->new({
            CONSTANTS => {
                title   => 'A Demo Page',
                author  => 'Joe Random Hacker',
                version => 3.14,
            },
        };
  • CONSTANT_NAMESPACE

    По умолчанию константы доступны через пространство имен 'constants'.

        [% constants.title %]

    Опция CONSTANTS_NAMESPACE используется для установки альтернативного пространства имен.

        my $template = Template->new({
            CONSTANTS => {
                title   => 'A Demo Page',
                # ...etc...
            },
            CONSTANTS_NAMESPACE => 'const',
        };

    В этом случае доступ к константам можно получить следующим образом:

        [% const.title %]
  • NAMESPACE

    Описанный выше механизм хранения переменных - это частный случай управления пространствами имен. Можно определять обработчики пространств имен для обеспечения возможности использования различных механизмов анализа переменных в различных пространствах имен.

    Внутри модуль Template преобразует следующий конфигурацию конструктора:

        my $template = Template->new({
    	CONSTANTS => {
    	    title   => 'A Demo Page',
    	    # ...etc...
    	},
    	CONSTANTS_NAMESPACE => 'const',
        };

    в подобную:

        my $template = Template->new({
    	NAMESPACE => {
    	    const => Template::Namespace::Constants->new({
    		title   => 'A Demo Page',
    		# ... и т.д. ...
    	    }),
    	},
        };

    Можно использовать этот механизм для определения множества пространств имен, или для установки собственных обработчиков.

        my $template = Template->new({
    	NAMESPACE => {
    	    site => Template::Namespace::Constants->new({
    		title   => "Wardley's Widgets",
    		version => 2.718,
    	    }),
    	    author => Template::Namespace::Constants->new({
    		name  => 'Andy Wardley',
    		email => 'abw@andywardley.com',
    	    }),
    	    voodoo => My::Namespace::Handler->new( ... ),
    	},
        };

    Теперь вы можете использовать 2 пространства имен констант, например:

        [% site.title %]
        [% author.name %]

    и, кроме того, свой собственный обработчик пространства имен, установленный для 'voodoo'.

        [% voodoo.magic %]

    Чтобы изучить устройство обработчика пространства имен изнутри, смотрите пример в Template::Namespace::Constants.

Опции обработки шаблона

Следующие опции используются для определения различных шаблонов, которые должны быть обработаны до, после, вместо или в ходе обработки шаблона, указанного в качестве первого аргумента метода Template process(). С помощью этих опций можно выполнять различные полезные задачи, такие как добавление стандартных заголовков и подвалов ко всем страницам, обертывание вывода страницы в другие шаблоны, предопределение переменных или исполнение задач по инициализии или очистке, автоматическая генерация краткого содержания страниц, элементов навигации, и т.д.

На внутреннем уровне задача обработки шаблона передается модулю Template::Service, который как и следует ожидать, также имеет метод process(). Любые шаблоны, определенные с помощью опции PRE_PROCESS, обрабатываются в первую очередь и любой сгенерированный ими вывод добавляется в буфер вывода. Затем обрабатывается главный шаблон или, если определены один или несколько шаблонов в опции PROCESS, то вместо главного по очереди обрабатываются они. В последнем случае, шаблоны PROCESS отвечают за обработку главного шаблона, например, путем использования директивы:

    [% PROCESS $template %]

Вывод, сгенерированный в ходе обработки главного шаблона или шаблона(ов) PROCESS, затем оборачивается в шаблоны WRAPPER, если они определены. Шаблонам WRAPPER нет необходимости явно заботиться об обработке шаблона, потому что он уже подготовлен для них. Вместо этого шаблоны WRAPPER получают доступ к контенту, который они обертывают, через переменную 'content'.

    wrapper before
    [% content %]
    wrapper after

Этот сгенерированный из главного и/или любых PROCESS или WRAPPER шаблонов вывод добавляется в буфер вывода. В заключение, обрабатываются любые шаблоны, определенные с помощью опции POST_PROCESS, и их вывод также добавляется в буфер вывода, который затем возвращается.

Если в ходе обработки главного шаблона генерируется исключение, то любой подходящий шаблон (или шаблоны), определенный через опцию ERROR, будет обработан вместо него. Если шаблон ошибки определен и успешно обработан, его вывод будет добавлен в буфер вывода вместо шаблона, который сгенерировал ошибку и обработка будет продолжена с применением WRAPPER или POST_PROCESS шаблонов. Если подходящая опция ERROR не определена, или если ошибка произойдет в одном из шаблонов PRE_PROCESS, WRAPPER или POST_PROCESS, обработка будет немедленно прервана и будет возвращена ошибка.

  • PRE_PROCESS, POST_PROCESS

    Эти опции могут содержать имя (имена) файлов шаблонов (относительно INCLUDE_PATH), которые будут немедленно обработаны до и/или после каждого шаблона. Это не относится к шаблонам, которые обрабатываются в документе через директивы INCLUDE, PROCESS, WRAPPER и т.д.

        my $template = Template->new({
    	PRE_PROCESS  => 'header',
    	POST_PROCESS => 'footer',
        };

    Несколько шаблонов можно передать с помощью ссылки на массив. Каждый шаблон будет обработан в определенном порядке.

        my $template = Template->new({
    	PRE_PROCESS  => [ 'config', 'header' ],
    	POST_PROCESS => 'footer',
        };

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

        my $template = Template->new({
    	PRE_PROCESS  => 'config:header',
    	POST_PROCESS => 'footer',
        };

    Шаблоны PRE_PROCESS и POST_PROCESS вычисляются в том же окружении переменных, что и главный документ, и могут определять или изменять переменные шаблона для последующего использования.

    config:

        [% # set some site-wide variables
           bgcolor = '#ffffff'
           version = 2.718
        %]

    header:

        [% DEFAULT title = 'My Funky Web Site' %]
        <html>
        <head>
        <title>[% title %]</title>
        </head>
        <body bgcolor="[% bgcolor %]">

    footer:

        <hr>
        Version [% version %]
        </body>
        </html>

    Объект Template::Document, представляющий главный шаблон, который будет обработан, доступен внутри шаблонов PRE_PROCESS и POST_PROCESS как переменная 'template'. Таким же образом можно получить доступ к метаданным, определенным с помощью директивы META.

        $template->process('mydoc.html', $vars);

    mydoc.html:

        [% META title = 'My Document Title' %]
        blah blah blah
        ...

    header:

        <html>
        <head>
        <title>[% template.title %]</title></head>
        <body bgcolor="[% bgcolor %]">
  • PROCESS

    С помощью опции PROCESS можно задать файл(ы) шаблонов (относительно INCLUDE_PATH), которые будут обрабатываться вместо главного шаблона, который передается методу Template process(). Это можно использовать для применения нескольких последовательных оберток для всех шаблонов, как и при использовании шаблонов PRE_PROCESS и POST_PROCESS.

        my $template = Template->new({
    	PROCESS  => 'content',
        };
        # обрабатывается 'content' вместо 'foo.html'
        $template->process('foo.html');

    Ссылка на оригинальный шаблон доступна через переменную 'template'. Можно использовать элементы метаданных определенные в нем, а сам шаблон можно обработать, указав его как ссылку на переменную (с префиксом '$') директивам INCLUDE, PROCESS или WRAPPER.

    content:

        <html>
        <head>
        <title>[% template.title %]</title>
        </head>
    
        <body>
        [% PROCESS $template %]
        <hr>
        &copy; Copyright [% template.copyright %]
        </body>
        </html>

    foo.html:

        [% META
           title     = 'The Foo Page'
           author    = 'Fred Foo'
           copyright = '2000 Fred Foo'
        %]
        <h1>[% template.title %]</h1>
        Welcome to the Foo Page, blah blah blah

    Вывод:

        <html>
        <head>
        <title>The Foo Page</title>
        </head>
        <body>
        <h1>The Foo Page</h1>
        Welcome to the Foo Page, blah blah blah
        <hr>
        &copy; Copyright 2000 Fred Foo
        </body>
        </html>
  • WRAPPER

    Опция WRAPPER используется для указания одного или нескольких шаблонов, которые будут использованы как обертки вокруг главного шаблона. В первую очередь обрабатывается главный шаблон (или шаблон(ы) PROCESS) и полученный вывод передается через переменную 'content' шаблону (шаблонам) WRAPPER во время их обработки.

        my $template = Template->new({
    	WRAPPER => 'wrapper',
        };
        # обрабатывается 'foo', затем заворачивается в 'wrapper'
        $template->process('foo', { message => 'Hello World!' });

    wrapper:

        <wrapper>
        [% content %]
        </wrapper>

    foo:

        This is the foo file!
        Message: [% message %]

    Этот пример даст следующий вывод:

        <wrapper>
        This is the foo file!
        Message: Hello World!
        </wrapper>

    Можно установить более одного шаблона WRAPPER, установив опцию как ссылку на массив шаблонов. Шаблоны WRAPPER будут обработаны в обратном порядке - вывод каждого из них будет передаваться следующему (или точнее предыдущем, если учесть порядок обработки) как переменная 'content'. Это кажется замысловатым, но конечный результат в как раз соответствует указанному порядку вложенности оберток (от внешней к внутренней).

        my $template = Template->new({
    	WRAPPER => [ 'outer', 'inner' ],
        };
        # обрабатывается 'foo', затем заворачивается в 'inner', затем в 'outer'
        $template->process('foo', { message => 'Hello World!' });

    outer:

        <outer>
        [% content %]
        </outer>

    inner:

        <inner>
        [% content %]
        </inner>

    Полученный результат:

        <outer>
        <inner>
        This is the foo file!
        Message: Hello World!
        </inner>
        </outer>

    Один побочный эффект обработки "изнутри-наружу" опции WRAPPER (и также директивы WRAPPER) заключается в том, что любые переменные, установленные в шаблоне, который заворачивается, будут видны в шаблоне-обертке, но не в другом направлении.

    Вы можете использовать этот полезный эффект, устанавливая в ваших шаблонах определенные переменные, которые затем будут использоваться в шаблонах-обертках. Например, наш главный шаблон 'foo' может выглядеть так:

    foo:

        [% page = {
               title    = 'Foo Page'
               subtitle = 'Everything There is to Know About Foo'
               author   = 'Frank Oliver Octagon'
           }
        %]
        <p>
        Welcome to the page that tells you everything about foo
        blah blah blah...
        </p>

    Поскольку шаблон 'foo' обрабатывается до шаблона-обертки, структура данных 'page' определяется для использования в обертке.

    wrapper:

        <html>
          <head>
            <title>[% page.title %]</title>
          </head>
          <body>
            <h1>[% page.title %]</h1>
            <h2>[% page.subtitle %]</h1>
            <h3>by [% page.author %]</h3>
            [% content %]
          </body>
        </html>

    Этим достигается такой же эффект, что и при использовании элементов META, которые доступны через переменную 'template' (которые вы по-прежнему вольны использовать в шаблонах WRAPPER), но дает большую гибкость в выборе типа и сложности данных, которые вы можете определить.

  • ERROR

    Опция ERROR (или ERRORS, если вам так больше нравится) используется для указания шаблона или определения хэша, связывающего типы исключений с шаблонами, используемыми для обработки ошибок. Если внутри шаблона возникает неперехваченное исключение, вместо него будет обработан соответствующий шаблон ошибки.

    Если указать опции одиночное значение, то этот шаблон будет обрабатываться для всех неперехваченных исключений.

        my $template = Template->new({
    	ERROR => 'error.html'
        });

    Если опция ERROR - ссылка на хеш, то предполагается, что ключи этого хеша - типы исключений и будет выбран подходящий шаблон для данного исключения. Для общего случая можно указать шаблон 'default'. Вы можете использовать 'ERRORS' вместо 'ERROR', если находите это название более подходящим для данного случая.

        my $template = Template->new({
    	ERRORS => {
    	    user     => 'user/index.html',
    	    dbi      => 'error/database',
    	    default  => 'error/default',
    	},
        });

    В данном примере, любые возбужденные исключения 'user' приведут к обработке шаблона 'user/index.html', ошибки 'dbi' обрабатываются шаблоном 'error/database', а все остальные шаблоном 'error/default'. Любые шаблоны PRE_PROCESS и/или POST_PROCESS также будут применены к этим шаблонам ошибок.

    Обратите внимание на то, что типы исключений имеют иерархию, и обработчик 'foo' будет также перехватывать все ошибки 'foo.*' (например, foo.bar, foo.bar.baz), если не определен более подходящий обработчик. Заключайте типы исключений, содержащие точки, в кавычки, чтобы быть уверенным, что Perl не склеит их в одну строку (например 'user.passwd' интерпретируется как 'user'.'passwd').

        my $template = Template->new({
    	ERROR => {
    	    'user.login'  => 'user/login.html',
    	    'user.passwd' => 'user/badpasswd.html',
    	    'user'        => 'user/index.html',
    	    'default'     => 'error/default',
    	},
        });

    В этом примере, любой шаблон обрабатываемый объектом $template, или другие шаблоны или код, вызываемые изнутри, могут возбудить исключение 'user.login', которое будет обработано шаблоном 'user/login.html'. Аналогично, исключение 'user.passwd' имеет свой шаблон-обработчик 'user/badpasswd.html', в то время как все остальные исключения 'user' или 'user.*' приведут к использованию шаблона 'user/index.html'. Оставшиеся исключения обрабатываются 'error/default'.

    Исключение можно возбудить с помощью директивы THROW внутри шаблона,

        [% THROW user.login 'no user id: please login' %]

    или вызвав метод throw() текущего объекта Template::Context,

        $context->throw('user.passwd', 'Incorrect Password');
        $context->throw('Incorrect Password');    # тип 'undef'

    или из кода Perl, вызвав die() с объектом Template::Exception,

        die (Template::Exception->new('user.denied', 'Invalid User ID'));

    или простым вызовом die() со строкой-сообщением об ошибке. Этот die() будет автомагически перехвачен и преобразован в исключение типа 'undef', которое затем может быть обработано обычным способом.

        die "I'm sorry Dave, I can't do that";

Опции времени исполнения шаблонов

  • EVAL_PERL

    Этот флаг используется для разрешения/запрета вычисления блоков PERL и/или RAWPERL. По умолчанию, опция запрещена и любой встретившийся блок PERL или RAWPERL приведет к исключению типа 'perl' с сообщением 'EVAL_PERL not set'. Тем не менее не забывайте, что любой блок RAWPERL должен всегда содержать корректный Perl-код, вне зависимости от установки флага EVAL_PERL. Парсер не сможет скомпилировать шаблоны с блоками RAWPERL, содержащими ошибки, и возбудит исключение 'file'.

    При использовании скомпилированных шаблонов (смотри COMPILE_EXT и COMPILE_DIR), EVAL_PERL может проявится в момент компиляции шаблона, и позже, когда шаблоны будут обрабатываться возможно в контексте, отличном от того, в котором они были скомпилированы.

    Если EVAL_PERL установлен в момент компиляции шаблона, то все блоки PERL и RAWPERL будут включены в скомпилированный шаблон. Если опция EVAL_PERL не установлена, то будет сгенерирован perl-код, который всегда генерирует исключение 'perl' с сообщением 'EVAL_PERL not set' независимо от окружения, в котором скомпилированный код шаблона будет исполняться.

    Таким образом, необходимо устанавливать EVAL_PERL, если вы хотите, чтобы блоки PERL и RAWPERL были включены в скомпилированные шаблоны.

    В последствии при использовании другого вызова Template Toolkit, эти предварительно скомпилированные шаблоны могут быть снова обработаны. Если во время компиляции опция EVAL_PERL была установлена, вывод любых блоков RAWPERL будет включен в скомпилированные шаблоны и будет выполнен во время обработки шаблона, независимо от того установлена ли опция EVAL_PERL.

    Обычные блоки PERL немного более требовательны. Если флаг EVAL_PERL не установлен в текущем контексте, который пытается выполнить блок, то будет возбуждено знакомое исключение 'perl' с сообщением 'EVAL_PERL not set'.

    Таким образом, можно скомпилировать шаблоны, включающие блоки PERL, но по необходимости запретить их при дальнейшем использовании. Тем не менее имейте в виду, что блок PERL может содержать perl-код "BEGIN { # some code }", который будет всегда исполняться независимо от текущего статуса EVAL_PERL. (Примечание переводчика - Последнее утверждение о блоке BEGIN {} кажется является ошибочным, поскольку исключение генерируется до того, как запускается eval, исполняющий блок PERL. Во всяком случае для Template Toolkit версии 2.13 это было именно так. Возможно, в последующих релизах модуль будет вести себя так, как описано выше). Таким образом, если вы устанавливаете EVAL_PERL при компиляции шаблонов, предполагается, что вы доверяете содержимому шаблонов. В противном случае, вам придется только надеяться, что включенный код не приведет к непредсказуемым результатам при последующем выполнении в другом окружении и не станет источником серьезных неприятностей. Если вы не хотите сталкиваться с подобными проблемами, следует принять установки по умолчанию и оставить EVAL_PERL запрещенным.

  • OUTPUT

    Место для вывода по умолчанию или дескриптор. Эта опция может быть: именем файла (если не указан абсолютный путь, то относительно OUTPUT_PATH, если опция определена, или текущей рабочей директории); файловым дескриптором (например, GLOB или IO::Handle), открытым на запись; ссылкой на текстовую строку, к которой будет добавляться вывод (строка не очищается); ссылкой на функцию, которой при вызове в качестве аргумента передается текст вывода; ссылкой на массив, в который вывод будет выталкивается функцией push(); или ссылкой на любой объект, поддерживающий метод print(). Последняя опция включает объект Apache::Request, который передается в качестве аргумента обработчикам Apache/mod_perl.

    пример 1 (имя файла):

        my $template = Template->new({
    	OUTPUT => "/tmp/foo",
        });

    пример 2 (текстовая строка):

        my $output = '';
        my $template = Template->new({
    	OUTPUT => \$output,
        });

    пример 3 (дескриптор файла):

        open (TOUT, "> $file") || die "$file: $!\n";
        my $template = Template->new({
    	OUTPUT => \*TOUT,
        });

    пример 4 (функция):

        sub output { my $out = shift; print "OUTPUT: $out" }
        my $template = Template->new({
    	OUTPUT => \&output,
        });

    пример 5 (ссылка на массив):

        my $template = Template->new({
    	OUTPUT => \@output,
        })

    пример 6 (обработчик Apache/mod_perl):

        sub handler {
    	my $r = shift;
    	my $t = Template->new({
    	    OUTPUT => $r,
    	});
    	...
        }

    Место для вывода по умолчанию OUTPUT переопределяется третьим параметром вызова метода Template process(). Тип этого параметр может быть любым из перечисленных выше.

        $t->process($file, $vars, "/tmp/foo");
        $t->process($file, $vars, "bar");
        $t->process($file, $vars, \*MYGLOB);
        $t->process($file, $vars, \@output);
        $t->process($file, $vars, $r);  # Apache::Request
        ...
  • OUTPUT_PATH

    Опция OUTPUT_PATH позволяет задать каталог, в который будут сохраняться выходные файлы. Выходной файл может быть определен с помощью опции OUTPUT, или передан по имени третьим параметром вызова метода Template process().

        my $template = Template->new({
    	INCLUDE_PATH => "/tmp/src",
    	OUTPUT_PATH  => "/tmp/dest",
        });
        my $vars = {
    	...
        };
        foreach my $file ('foo.html', 'bar.html') {
    	$template->process($file, $vars, $file)
    	    || die $template->error();
        }

    В этом примере будут прочитаны входные файлы '/tmp/src/foo.html' и '/tmp/src/bar.html', а сгенерированный вывод будет сохранен в '/tmp/dest/foo.html' и '/tmp/dest/bar.html' соответственно.

  • DEBUG

    Опция DEBUG используется для включения отладки внутри различных модулей, составляющих Template Toolkit. Модуль Template::Constants определяет набор констант DEBUG_XXXX, которые можно объединять с помощью логического опреатора OR, '|'.

        use Template::Constants qw( :debug );
        my $template = Template->new({
    	DEBUG => DEBUG_PARSER | DEBUG_PROVIDER,
        });

    Для удобства, можно передавать строку, содержащую список опций отладки в нижнем регистре, разделенных любыми небуквенными символами.

        my $template = Template->new({
    	DEBUG => 'parser, provider',
        });

    Можно использовать следующие флаги DEBUG_XXXX:

    • DEBUG_SERVICE

      Разрешить общие отладочные сообщения для модуля Template::Service.

    • DEBUG_CONTEXT

      Разрешить общие отладочные сообщения для модуля Template::Context.

    • DEBUG_PROVIDER

      Разрешить общие отладочные сообщения для модуля Template::Provider.

    • DEBUG_PLUGINS

      Разрешить общие отладочные сообщения для модуля Template::Plugins.

    • DEBUG_FILTERS

      Разрешить общие отладочные сообщения для модуля Template::Filters.

    • DEBUG_PARSER

      Этот флаг вынуждает Template::Parserгенерировать отладочные сообщения, которые показывают сгенерированный в ходе разбора и компиляции каждого шаблона perl-код.

    • DEBUG_UNDEF

      Эта опция вынуждает Template Toolkit генерировать исключение 'undef' при встрече неопределенного значения переменной.

    • DEBUG_DIRS

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

      Например, следующий фрагмент шаблона:

          Hello World

      сгенерирует следующий вывод:

          ## input text line 1 :  ##
          Hello
          ## input text line 2 : World ##
          World
    • DEBUG_ALL

      Разрешить все отладочные сообщения.

    • DEBUG_CALLER

      Эта опция приводит к добавлению имени и номера строки вызывающего файла ко всем отладочным сообщениям, которые не завершаются символом новой строки.

  • DEBUG_FORMAT

    Опция DEBUG_FORMAT используется для определения форматирующей строки для отладочных сообщений, сгенерированных через описанную выше опцию DEBUG_DIRS. Все вхождения '$file', '$line' или '$text' будут заменены на текущее имя файла, номер строки и текст директивы соответственно. Обратите внимание на то, что форматирующие строки заключены в одинарные кавычки, для того чтобы perl не интерполировал эти символы как переменные.

        my $template = Template->new({
    	DEBUG => 'dirs',
    	DEBUG_FORMAT => '<!-- $file line $line : [% $text %] -->',
        });

    Следующий фрагмент шаблона:

        [% foo = 'World' %]
        Hello [% foo %]

    сгенерирует такой вывод:

        <!-- input text line 2 : [% foo = 'World' %] -->
        Hello <!-- input text line 3 : [% foo %] -->World

    Для установки формата отладочных сообщений внутри шаблона можно использовать директиву DEBUG.

        [% DEBUG format '<!-- $file line $line : [% $text %] -->' %]

Опции кеширования и компиляции

  • CACHE_SIZE

    Модуль Template::Provider кеширует шаблоны, чтобы избежать повторной компиляции файлов шаблонов или блоков, при их повторном использовании. Опция CACHE_SIZE используется для ограничения числа скомпилированных шаблонов, которые модуль будет кешировать.

    По умолчанию, CACHE_SIZE имеет неопределенное значение и все скомпилированные шаблоны кешируются. Если значение опции положительное число, кеш будет ограничен на хранение не более указанного числа скомпилированных шаблонов. Когда загружается и компилируется новый шаблон, а кеш заполнен (т.е. число элементов == CACHE_SIZE), самый давно не использовавшийся шаблон удаляется, чтобы освободить место для нового.

    Установка CACHE_SIZE в 0 запрещает кеширование.

        my $template = Template->new({
            CACHE_SIZE => 64,   # кешировать только 64 скомпилированных шаблона
        });
        my $template = Template->new({
            CACHE_SIZE => 0,   # не кешировать скомпилированные шаблоны
        });
  • COMPILE_EXT

    Начиная с версии 2 Template Toolkit предоставляет возможность компилировать шаблоны в код Perl и сохранять их на диск для последующего использования (т.е. постоянный кеш). Опция COMPILE_EXT используется для определения расширения для файлов скомпилированных шаблонов. По умолчанию, опция имеет неопределенное значение и попытки прочитать или записать скомпилированные шаблоны не предпринимаются.

        my $template = Template->new({
    	COMPILE_EXT => '.ttc',
        });

    Если COMPILE_EXT определена (а COMPILE_DIR нет, смотри ниже), то скомпилированные шаблоны с расширением COMPILE_EXT будут записываться в каталог, из которого исходный файл шаблона был загружен.

    Компиляция и последующее повторное использование шаблонов происходит автоматически всякий раз, когда установлены опции COMPILE_EXT или COMPILE_DIR. Template Toolkit автоматически загрузит и использует скомпилированные файлы, если найдет их на диске. Если соответствующий исходный файл был изменен после того как он был скомпилирован и сохранен, Template Toolkit загрузит и перекомпилирует исходник и сохранит новую версию на диск.

    Эта форма постоянного кеша дает значительную экономию времени и ресурсов, необходимых для перезагрузки шаблона. Скомпилированные шаблоны могут быть перезагружены посредством простого вызова require(), освобождая Perl от разбора и компиляции. Это Правильная Вещь.

  • COMPILE_DIR

    Опция COMPILE_DIR используется для определения альтернативного корня каталогов, в которых будут сохраняться скомпилированные шаблоны.

        my $template = Template->new({
    	COMPILE_DIR => '/tmp/ttc',
        });

    Опция COMPILE_EXT также может быть использована для явного определения расширения, которое будет добавляться к этим файлам.

        my $template1 = Template->new({
    	COMPILE_DIR => '/tmp/ttc',
    	COMPILE_EXT => '.ttc1',
        });
        my $template2 = Template->new({
    	COMPILE_DIR => '/tmp/ttc',
    	COMPILE_EXT => '.ttc2',
        });

    Когда COMPILE_EXT не определена, файлы скомпилированных шаблонов сохраняются с исходными именами файлов, но в другом дереве каталогов.

    Путь каждого каталога из INCLUDE_PATH полностью воспроизводится внутри каталога COMPILE_DIR. Этот пример:

        my $template = Template->new({
            COMPILE_DIR  => '/tmp/ttc',
            INCLUDE_PATH => '/home/abw/templates:/usr/share/templates',
        });

    приведет к созданию следующей структуры каталогов:

        /tmp/ttc/home/abw/templates/
        /tmp/ttc/usr/share/templates/

    Скомпилированные шаблоны файлов, загруженные из различных каталогов INCLUDE_PATH, будут сохранены в соответствующих каталогах в COMPILE_DIR.

    На платформах Win32 имя файла может начинаться с имени устройства и двоеточия. Например,

        C:/My Templates/header

    Двоеточие будет молча вырезано из имени файла при добавлении к значению COMPILE_DIR, чтобы предотвратить использование неправильных имен файлов. Двоеточия в элементах COMPILE_DIR останутся без изменений. Например:

        # только в Win32
        my $template = Template->new({
    	DELIMITER    => ';',
    	COMPILE_DIR  => 'C:/TT2/Cache',
    	INCLUDE_PATH => 'C:/TT2/Templates;D:/My Templates',
        });

    Это приведет к созданию следующих каталогов кеша:

        C:/TT2/Cache/C/TT2/Templates
        C:/TT2/Cache/D/My Templates

Плагины и фильтры

  • PLUGINS

    Опция PLUGINS используется для определения ссылки на хеш, связывающий имена плагинов с названиями модулей Perl. Ряд плагинов (например, 'table', 'cgi', 'dbi' и т.д.) уже определены и связаны с соответсвующими модулями Template::Plugin::*. Они могут быть переопределены в хеше PLUGINS.

        my $template = Template->new({
    	PLUGINS => {
    	    cgi => 'MyOrg::Template::Plugin::CGI',
        	    foo => 'MyOrg::Template::Plugin::Foo',
    	    bar => 'MyOrg::Template::Plugin::Bar',
    	},
        });

    Директива USE используется для создания объектов плагинов и делает это посредством вызова метода plugin() текущего объекта Template::Context. Если имя плагина определено в хеше PLUGINS, соответствующий модуль Perl загружается посредством require(). Затем объект контекста вызывает метод класса load(), который должен вернуть имя класса (в общем случае и по умолчанию) или объект-прототип, вызов метода new() которого можно использовать для создания индивидуальных объектов плагинов.

    Если имя плагина не определено в хеше PLUGINS, вступают в силу опции PLUGIN_BASE и/или LOAD_PERL.

  • PLUGIN_BASE

    Если плагин не определен в хеше PLUGINS, опция PLUGIN_BASE используется для конструирования правильного имени perl-модуля, который может быть удачно загружен.

    PLUGIN_BASE может быть определена как единичное значение или как ссылка на массив значений. Значение PLUGIN_BASE по умолчанию 'Template::Plugin' всегда добавляется в конец списка PLUGIN_BASE (единичное значение перед этим преобразуется в список). Каждое значение должно содержать пространство имен Perl, к которому добавляется запрашиваемое имя плагина.

    Пример 1:

        my $template = Template->new({
    	PLUGIN_BASE => 'MyOrg::Template::Plugin',
        });
        [% USE Foo %]    # => MyOrg::Template::Plugin::Foo
                           или       Template::Plugin::Foo

    Пример 2:

        my $template = Template->new({
    	PLUGIN_BASE => [   'MyOrg::Template::Plugin',
    			 'YourOrg::Template::Plugin'  ],
        });
        [% USE Foo %]    # =>    MyOrg::Template::Plugin::Foo
                           или YourOrg::Template::Plugin::Foo
                           или          Template::Plugin::Foo 
  • LOAD_PERL

    Если не удается загрузить плагин с помощью PLUGINS или PLUGIN_BASE, поставщик плагинов пытается загрузить модуль без использования добавочного префикса в пути модуля. Это позволяет загружать и использовать в качестве плагинов обычные perl-модули (т.е. те модули, которые не находятся внутри Template::Plugin или других подобных пространств имен).

    По умолчанию, опция LOAD_PERL установлена в 0 и Template Toolkit не пытается загрузить модули, которые явно не определены в хеше PLUGINS или не находятся внутри пакетов, определенных в PLUGIN_BASE.

    Плагины, загружаемые с помощью PLUGINS или PLUGIN_BASE, получают ссылку на объект текущего контекста в качестве первого аргумента конструктора new(). Для модулей, загружаемых с помощью LOAD_PERL, предполагается, что они не следуют интерфейсу плагина. Они должны предоставлять метод new() для создания объектов, но ссылка на объект текущего контекста им в качестве первого аргумента не передается. Модули-плагины должны содержать метод класса load() (или унаследовать метод по умолчанию от базового класса Template::Plugin), который вызывается при первой загрузке плагина. Обычные модули Perl могут не содержать такого метода. Во всем остальном обычные perl-модули и плагины Template Toolkit идентичны.

    Если какой-то perl-модуль не следует общему, но не обязательному, соглашению о конструкторе new(), можно написать простой плагин-обертку, предоставляющий интерфейс для работы с этим модулем.

  • FILTERS

    Опция FILTERS используется для определения собственных фильтров, которые могут использоваться в директиве FILTER как любые другие. Собственные фильтры добавляются к стандартным фильтрам, которые доступны по умолчанию. Фильтры, определенные через эту опцию, будут маскировать любые стандартные одноименные фильтры.

    Опция FILTERS должна быть определена как ссылка на хеш, в котором имена ключей являются именами фильтров. Соответсвующие этим именам значения должны быть ссылкой на массив, содержащий ссылку на функцию и флаг, определяющий тип фильтра (0 - статический или 1 - динамический). Также фильтр можно определить как ссылку на функцию. В этом случае предполагается, что фильтр будет статическим.

        $template = Template->new({
            FILTERS => {
                'sfilt1' =>   \&static_filter,      # статический
                'sfilt2' => [ \&static_filter, 0 ], # тоже самое
                'dfilt1' => [ \&dyanamic_filter_factory, 1 ],
            },
        });

    Дополнительные фильтры можно указать в любое время через вызов метода define_filter() текущего объекта Template::Context. Методу передается имя фильтра, ссылка на функцию фильтра и необязательный параметр-флаг, указывающий, является ли фильтр динамическим.

        my $context = $template->context();
        $context->define_filter('new_html', \&new_html);
        $context->define_filter('new_repeat', \&new_repeat, 1);

    В статических фильтрах для всех вызовов используется ссылка на одну функцию. Фильтры, которым не передаются никакие параметры конфигурации (например, 'html') могут быть реализованы статически. Когда запрашивается такой фильтр, возвращается просто ссылка на функцию. Функция вызывается для обработки вывода блока, который передается ей в качестве единственного аргумента. Функция должна вернуть измененный текст.

        sub static_filter {
            my $text = shift;
            # модифицируем $text...
            return $text;
        }

    Следующий фрагмент шаблона:

        [% FILTER sfilt1 %]
        Blah blah blah.
        [% END %]

    эквивалентен такому вызову:

        &static_filter("\nBlah blah blah.\n");

    Фильтры, которым можно передавать параметры (например, 'truncate'), должны быть реализованы динамически. В этом случае, используется функция, которая должна быть 'фабрикой' фильтров, то есть функцией, создающей уникальную функцию-фильтр для каждого запроса. В качестве первого аргумента этой производящей функции передается текущий объект Template::Context, за которым следуют дополнительные параметры, определенные в вызове фильтра. Функция должна вернуть ссылку на другую функцию (чаще всего анонимную), которая реализует фильтр.

        sub dynamic_filter_factory {
            my ($context, @args) = @_;
            return sub {
                my $text = shift;
                # модифицируем $text...
                return $text;
            }
        }

    Следующий фрагмент шаблона:

        [% FILTER dfilt1(123, 456) %]
        Blah blah blah
        [% END %]              

    примерно эквивалентен такому коду:

        my $filter = &dynamic_filter_factory($context, 123, 456);
        &$filter("\nBlah blah blah.\n");

    Дополнительные примеры смотри в описании директивы FILTER.

Совместимость, настройка и расширение

  • V1DOLLAR

    В версии 1 Template Toolkit, перед любой переменной шаблона можно было поставить необязательный символ '$' и он просто игнорировался.

        # ВЕРСИЯ 1
        [% $foo %]       ===  [% foo %]
        [% $hash.$key %] ===  [% hash.key %]

    Для вычисления значения переменной использовалась конструкция '${' ... '}'. Обычно это использовалось для получения значения хеша по ключу, сохраненному в переменной.

    Например:

        my $vars = {
            users => {
                aba => { name => 'Alan Aardvark', ... },
                abw => { name => 'Andy Wardley', ... },
                ...
            },
            uid => 'aba',
            ...
        };
        $template->process('user/home.html', $vars)
            || die $template->error(), "\n";

    'user/home.html':

        [% user = users.${uid} %]     # users.aba
        Name: [% user.name %]         # Alan Aardvark

    Это порождало несовместимость со строками, заключенными в двойные кавычки, а также режимом INTERPOLATE, в котором символа '$' в тексте достаточно для выделения переменной, которую необходимо вычислить, а дополнительные фигурные скобки используются для явного выделения имени переменной при необходимости. Отметим, что такое использование, помимо прочего, согласуется с соглашениями, существующими в UNIX и Perl.

        # интерполяция внутри строки в двойных кавычках
        [% name = "$title ${user.name}" %]
        # INTERPOLATE = 1
        <img src="$images/help.gif"></a>
        <img src="$images/${icon.next}.gif">

    В версии 2, эти несовместимости были устранены и синтаксис стал более ясным. '$', предшествующий имени переменной сейчас однозначно указывает на то, что имя переменной перед использованием должно быть интерполировано (т.е. вычислено и заменено на значение переменной). Приведенный раньше пример из версии 1:

        # ВЕРСИЯ 1
        [% user = users.${uid} %]
        Name: [% user.name %]

    в версии 2 может быть упрощен следующим образом:

        # ВЕРСИЯ 2
        [% user = users.$uid %]
        Name: [% user.name %]

    Предшествующий знак доллара больше не игнорируется и так же означает интерполяцию, как и комбинация '${' ... '}' в версии 1. Фигурные скобки по прежнему можно использовать при необходимости для явного указания имени интерполируемой переменной.

    Например:

        [% user = users.${me.id} %]
        Name: [% user.name %]

    Это правило применяется ко всем переменным, как внутри директив, так и в тексте при обработке с установленной опцией INTERPOLATE. Это означает вам не следует (если вы так раньше делали) добавлять предшествующий '$' к переменной внутри директивы, если только вы точно не хотите, чтобы она была интерполирована.

    Один очевидный побочный эффект заключается в том, что шаблоны версии 1 с переменными, которым предшествует '$', не будут обрабатываться как ожидается. Имея следующие определения переменных,

        [% foo = 'bar'
           bar = 'baz'
        %]

    в версии 1 мы получим следующую интерпретацию:

        # ВЕРСИЯ 1
        [% $foo %] => [% GET foo %] => bar

    в то время как версия 2 интерпретирует это так:

        # ВЕРСИЯ 2
        [% $foo %] => [% GET $foo %] => [% GET bar %] => baz

    В версии 1, '$' игнорировался - мы получали и выводили значение переменной 'foo'. В версии 2, переменная '$foo' вначале вычисляется и получается имя переменной 'bar', значение которой затем выводится.

    Использование дополнительного '$' не рекомендовалось, но для обеспечения обратной совместимости с шаблонами версии 1, которые могут зависеть от этой "возможности", можно установить опцию V1DOLLAR в 1 (по умолчанию: 0), чтобы вернуть прежнее поведение и игнорировать предшествующие символы '$'.

        my $template = Template->new({
    	V1DOLLAR => 1,
        });
  • LOAD_TEMPLATES

    Опция LOAD_TEMPLATE используется для установки ссылки на массив объектов класса Template::Provider или порожденных классов, которые будут отвечать за загрузку и компиляцию шаблонов.

        my $template = Template->new({
            LOAD_TEMPLATES => [
                MyOrg::Template::Provider->new({ ... }),
                Template::Provider->new({ ... }),
            ],
        });

    Когда в шаблоне встречается директива PROCESS, INCLUDE или WRAPPER, имя, указанное в директиве, может ссылаться на локально определенный блок BLOCK или имя файла относительно INCLUDE_PATH (или абсолютный или относительный путь к файлу, если установлены соответственно опции ABSOLUTE или RELATIVE). Если определение BLOCK не может быть найдено (смотри обсуждение области видимости BLOCK в описании метода Template::Context template()), каждый из объектов-поставщиков, опредленных в LOAD_TEMPLATES, по очереди опрашивается через вызов метода fetch(), чтобы выяснить может ли он предоставить запрашиваемый шаблон. Каждый поставщик может вернуть скомпилированный шаблон, ошибку или отказ от обслуживания запроса. В последнем случае ответственность передается следующему поставщику. Если ни один из поставщиков не может обслужить запрос, возвращается ошибка 'not found'. Такой же в основе механизм поставщиков используется для директивы INSERT, но он пропускает любые определения BLOCK и не предпринимает попытки разобрать или обработать содержимое файла шаблона.

    Это реализация модели 'Цепочка ответственности' ('Chain of Responsibility'), описанной в "Design Patterns", Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides), Addision-Wesley, ISBN 0-201-63361-2, page 223.

    Если LOAD_TEMPLATES не определена, будет инициализирован одиночный объект поставщика по умолчанию с текущими параметрами конфигурации. Например, опция Template::Provider INCLUDE_PATH может быть указана в конфигурации Template и будет корректно передана констуруктору поставщика.

        my $template = Template->new({
    	INCLUDE_PATH => '/here:/there',
        });
  • LOAD_PLUGINS

    Опция LOAD_PLUGINS используется для указания массива объектов-поставщиков (т.е. объектов реализующих метод fetch()), которые отвечают за загрузку и создание объектов-плагинов. Метод Template::Content plugin() опрашивает каждого поставщика по очереди по принципу 'Цепочки ответственности' аналогично методам template() и filter().

        my $template = Template->new({
            LOAD_PLUGINS => [
                MyOrg::Template::Plugins->new({ ... }),
                Template::Plugins->new({ ... }),
            ],
        });

    По умолчанию, создается одиночный объект Template::Plugins с текущим конфигурационным хешем. Элементы конфигурации, предназначенные для конструктора Template::Plugins могут быть добавлены в конфигурацию конструктора Template.

        my $template = Template->new({
    	PLUGIN_BASE => 'MyOrg::Template::Plugins',
    	LOAD_PERL   => 1,
        });
  • LOAD_FILTERS

    Опция LOAD_FILTERS используется для указания массива объектов-поставщиков (т.е. объектов реализующих метод fetch()), которые отвечают за возврат и/или создание функций-фильтров. Метод Template::Content filter() опрашивает каждого поставщика по очереди по принципу 'Цепочки ответственности' аналогично методам template() и plugin().

        my $template = Template->new({
    	LOAD_FILTERS => [
        	    MyTemplate::Filters->new(),
        	    Template::Filters->new(),
    	],
        });

    По умолчанию, для массива LOAD_FILTERS создается одиночный объект Template::Filters.

  • TOLERANT

    Флаг TOLERANT используется различными модулями-поставщиками Template Toolkit (Template::Provider, Template::Plugins, Template::Filters) для управления их поведением при возникновении ошибок. По умолчанию, о любых ошибках как таковых генерируется отчет, с одновременным запретом доступа к их источнику (шаблон, плагин, фильтр) и возбуждением исключения. Когда флаг TOLERANT установлен в любое истинное значение, ошибки будут без уведомления игнорироваться, а поставщик вместо этого вернет отказ от обслуживания (STATUS_DECLINED). Это позволяет вместо неудачного завершения после запроса поставщику, передать ответственность за предоставление источника следующему поставщику. Если все поставщики отклонят запрос на обслуживание либо по причине возникновения ошибки, либо из-за невозможности его выполнить, возбуждается исключение '<resource> not found'.

  • SERVICE

    Ссылка на объект Template::Service или его производного класса, которому модуль Template передает управление. Если опция не установлена, объект Template::Service автоматически создается с текущим конфигурационным хешем.

        my $template = Template->new({
    	SERVICE => MyOrg::Template::Service->new({ ... }),
        });
  • CONTEXT

    Ссылка на объект Template::Context, который используется для определения индивидуального окружения, в котором обрабатывается шаблон. Объект Template::Context передается в качестве единственного параметра функциям Perl, которые представляют "скомпилированные" шаблоны. Функции шаблона делают обратные вызовы через объект контекста, чтобы получить доступ к функциональности Template Toolkit, например, чтобы включить другой шаблон (директивы INCLUDE или PROCESS - методы include() и process() соответственно), использовать плагин (USE - plugin()), создать фильтр (filter()) или получить получить доступ к хранилищу (stash()), которое управляет определениями переменных через методы get() и set().

        my $template = Template->new({
    	CONTEXT => MyOrg::Template::Context->new({ ... }),
        });
  • STASH

    Ссылка на объект Template::Stash или его производного класса, который отвечает за управление переменными шаблона.

        my $stash = MyOrg::Template::Stash->new({ ... });
        my $template = Template->new({
            STASH => $stash,
        });

    Если опция не определена, создается объект хранилища (stash) по умолчанию. Для инициализации хранилища переменных используется опция конфигурации VARIABLES. Для обратной совместимости с версией 1 в качестве синонима VARIABLES можно использовать опцию PRE_DEFINE.

        my $template = Template->new({
    	VARIABLES => {
    	    id    => 'abw',
    	    name  => 'Andy Wardley',
    	},
        };
  • PARSER

    Модуль Template::Parser реализует объект парсера для компиляции шаблонов в perl-код, который затем может быть выполнен. Объект этого класса по умолчанию создается автоматически и затем используется объектом Template::Provider, как только шаблон загружен и требует компиляции. Опция PARSER используется для указания ссылки на объект альтернативного парсера.

        my $template = Template->new({
    	PARSER => MyOrg::Template::Parser->new({ ... }),
        });
  • GRAMMAR

    Элемент конфигурации GRAMMAR используется для определения альтернативной грамматики для парсера. Это позволяет сконструировать и использовать в Template Toolkit измененный или совершенно новый язык шаблонов.

    Исходные шаблоны компилируются в perl-код объектом Template::Parser, использующим по умолчанию Template::Grammar для определения структуры и семантики языка. Таким образом, скомпилированные шаблоны по сути "совместимы" друг с другом и нет ничего, что могло бы помешать компилировать и использовать шаблоны, использующих любое количество языков, в рамках одного и того же окружения обработки данных Template Toolkit (кроме обычных ограничений по времени и памяти).

    Файл Template::Grammar собирается из файла грамматики YACC (с использованием Parse::YAPP) и скелетного шаблона модуля. Эти файлы вместе с маленьким скриптом для перестройки грамматики поставляются в составе пакета в подкаталоге 'parser'. Вам не нужно ничего знать и беспокоится об этом, если только вы не хотите подправить язык шаблонов или создать свой собственный вариант. В этом же каталоге находится файл README с небольшой инструкцией, но подразумевается, что вы знаете, что делаете, если рискнете заняться этим. Если вы знаток парсеров LALR, это не вызовет у вас затруднений.

    Экземпляр Template::Grammar по умолчанию будет создан и использован автоматически, если элемент GRAMMAR не определен.

        use MyOrg::Template::Grammar;
        my $template = Template->new({
           	GRAMMAR = MyOrg::Template::Grammar->new();
        });

АВТОР

Индекс ] [ Руководство ] [ Наверх ]

Энди Уардли (Andy Wardley <abw@andywardley.com>)

http://www.andywardley.com/

ВЕРСИЯ

Индекс ] [ Руководство ] [ Наверх ]

Template Toolkit версия 2.14, дата релиза - 4 октября 2004.

АВТОРСКИЕ ПРАВА

Индекс ] [ Руководство ] [ Наверх ]

  Copyright (C) 1996-2004 Andy Wardley.  All Rights Reserved.
  Copyright (C) 1998-2002 Canon Research Centre Europe Ltd.

Этот модуль является свободно-распространяемым программным обеспечением; вы можете распространять и/или модифицировать его на тех же условиях, что и Perl.