Создание пользовательских фильтров
Фильтры — это мощные инструменты для форматирования и
изменения данных непосредственно в шаблонах Latte. Они предлагают чистый
синтаксис с использованием символа пайпа (|
) для преобразования
переменных или результатов выражений в желаемый выходной формат.
Что такое фильтры?
Фильтры в Latte — это, по сути, PHP-функции, разработанные специально
для преобразования входного значения в выходное. Они применяются с
помощью записи с пайпом (|
) внутри выражений шаблона
({...}
).
Удобство: Фильтры позволяют инкапсулировать распространенные задачи форматирования (например, форматирование дат, изменение регистра, усечение) или манипуляции с данными в повторно используемые единицы. Вместо повторения сложного PHP-кода в ваших шаблонах вы можете просто применить фильтр:
Читаемость: Использование фильтров делает шаблоны более понятными и более ориентированными на представление, поскольку логика преобразования перемещается в определение фильтра.
Контекстная чувствительность: Ключевым преимуществом фильтров в Latte является их способность быть контекстно-зависимыми. Это означает, что фильтр может распознавать тип содержимого, с которым он работает (HTML, JavaScript, простой текст и т. д.), и применять соответствующую логику или экранирование, что критически важно для безопасности и правильности, особенно при генерации HTML.
Интеграция с логикой приложения: Как и пользовательские функции, вызываемый PHP-объект, стоящий за фильтром, может быть замыканием (closure), статическим методом или методом экземпляра. Это позволяет фильтрам получать доступ к сервисам приложения или данным, если это необходимо, хотя их основной целью остается преобразование входного значения.
Latte по умолчанию предоставляет богатый набор стандартных фильтров. Пользовательские фильтры позволяют расширить этот набор форматированием и преобразованиями, специфичными для вашего проекта.
Если вам нужно выполнять логику, основанную на нескольких входах, или у вас нет основного значения для преобразования, вероятно, более подходящим будет использование пользовательской функции. Если вам нужно генерировать сложную разметку или управлять потоком шаблона, рассмотрите пользовательский тег.
Создание и регистрация фильтров
Существует несколько способов определения и регистрации пользовательских фильтров в Latte.
Прямая регистрация с помощью
addFilter()
Самый простой способ добавить фильтр — использовать метод
addFilter()
непосредственно на объекте Latte\Engine
. Вы указываете
имя фильтра (как он будет использоваться в шаблоне) и соответствующий
вызываемый PHP-объект.
Использование в шаблоне:
Передача аргументов:
Значение слева от пайпа (|
) всегда передается как первый
аргумент функции фильтра. Любые параметры, указанные после двоеточия
(:
) в шаблоне, передаются как следующие аргументы.
Регистрация с помощью расширения
Для лучшей организации, особенно при создании повторно используемых наборов фильтров или их распространении в виде пакетов, рекомендуемым способом является их регистрация в рамках расширения Latte:
Этот подход сохраняет логику вашего фильтра инкапсулированной и упрощает регистрацию.
Использование загрузчика фильтров
Latte позволяет регистрировать загрузчик фильтров с помощью
addFilterLoader()
. Это единственный вызываемый объект, который Latte
запросит для любого неизвестного имени фильтра во время компиляции.
Загрузчик возвращает вызываемый PHP-объект фильтра или null
.
Этот метод был в основном предназначен для ленивой загрузки фильтров с очень сложной инициализацией. Однако современные практики внедрения зависимостей (dependency injection) обычно справляются с ленивыми сервисами более эффективно.
Загрузчики фильтров добавляют сложности и, как правило, не
рекомендуются в пользу прямой регистрации с помощью addFilter()
или
в рамках расширения с помощью getFilters()
. Используйте загрузчики
только если у вас есть веская, специфическая причина, связанная с
проблемами производительности при инициализации фильтров, которые
нельзя решить иначе.
Фильтры, использующие класс с атрибутами
Еще один элегантный способ определения фильтров — использование
методов в вашем классе
параметров шаблона. Просто добавьте атрибут
#[Latte\Attributes\TemplateFilter]
к методу.
Latte автоматически распознает и зарегистрирует методы, помеченные
этим атрибутом, когда объект TemplateParameters
передается в шаблон. Имя
фильтра в шаблоне будет таким же, как имя метода (shortify
в данном
случае).
Контекстные фильтры
Иногда фильтру требуется больше информации, чем просто входное значение. Ему может потребоваться знать тип содержимого строки, с которой он работает (например, HTML, JavaScript, простой текст), или даже изменить его. Это ситуация для контекстных фильтров.
Контекстный фильтр определяется так же, как и обычный фильтр, но его
первый параметр должен быть типизирован как Latte\Runtime\FilterInfo
.
Latte автоматически распознает эту сигнатуру и при вызове фильтра
передаст объект FilterInfo
. Следующие параметры получат аргументы
фильтра как обычно.
$info->contentType
— это строковая константа из Latte\ContentType
(например, ContentType::Html
, ContentType::Text
, ContentType::JavaScript
и т.
д.) или null
, если фильтр применяется к переменной ({$var|filter}
).
Вы можете читать это значение, чтобы проверить входной контекст, и
записывать в него, чтобы объявить тип выходного контекста.
Устанавливая тип содержимого в HTML, вы сообщаете Latte, что строка, возвращаемая вашим фильтром, является безопасным HTML. Latte тогда не будет применять к этому результату свое стандартное автоматическое экранирование. Это критически важно, если ваш фильтр генерирует HTML-разметку.
Если ваш фильтр генерирует HTML, вы несете ответственность
за правильное экранирование любых входных данных, используемых в
этом HTML (как в случае вызова htmlspecialchars($formatted)
выше). Пренебрежение
этим может создать уязвимости XSS. Если ваш фильтр возвращает только
простой текст, вам не нужно устанавливать $info->contentType
.
Фильтры на блоках
Все фильтры, применяемые к блокам, должны быть контекстными. Это потому, что содержимое блока имеет определенный тип содержимого (обычно HTML), о котором фильтр должен знать.
Контекстные фильтры предоставляют мощный контроль над тем, как данные обрабатываются на основе их контекста, позволяют реализовать продвинутые функции и обеспечивают правильное поведение экранирования, особенно при генерации HTML-содержимого.