A free and open-source book on ZF3 for beginners


8.6. Примеры использования фильтров

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

8.6.1. Фильтры, приводящие входные данные к определенному типу

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

8.6.1.1. Фильтр ToInt

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

Класс ToInt имеет единственный метод filter().

Фильтр ToInt не будет приводить нескалярные значения. Если вы передадите ему массив, он вернет его как есть.

Ниже показан пример кода, демонстрирующий использование фильтра ToInt.

<?php
// Создаем фильтр ToInt.
$filter = new \Zend\Filter\ToInt();

// Фильтруем значение, приводя его к типу integer.
$filteredValue = $filter->filter('10'); // Возвращает (int) 10.
$filteredValue2 = $filter->filter(['10', '20']); // Возвращает массив как есть.

Во фрагменте выше мы передаем фильтру строку "10" (строка 6). Ожидаемое возвращаемое значение - 10 (типа integer).

В строке 7 мы передаем фильтру массив. Так как фильтр ToInt работает только со скалярными значениями, он возвращает массив как есть (без изменений) и выдает PHP-предупреждение.

8.6.1.2. Фильтр Boolean

Класс Boolean - это фильтр, предназначенный для приведения произвольных данных к булевому значению (true или false). Этот фильтр может использоваться для фильтрации полей формы флажка.

Его public-методы перечислены в таблице 8.3.

Таблица 8.3. Public-методы фильтра Boolean
Имя метода Описание
filter($value) Возвращает булевое представление $value.
setCasting($flag) Устанавливает флаг приведения.
getCasting() Возвращает флаг приведения.
setType($type) Задает типы, которые нужно приводить.
getType() Возвращает типы.
setTranslations($translations) Задает переводы.
getTranslations() Возвращает переводы.

Этот фильтр предоставляет несколько методов, позволяющих задать опции фильтрации (setCasting(), setType(), и setTranslations()).

Метод setCasting() позволяет выбрать один из двух режимов работы фильтра. Если флаг установлен в значение true, фильтр будет вести себя как оператор приведения PHP (к типу boolean). Иначе (если флаг установлен в значение false), он будет приводить только типы, определенные методом setType(), а другие значения возвращать как есть.

Метод фильтра setType() позволяет определить, какие типы нужно приводить. Этот метод принимает один аргумент $type, который может быть либо комбинацией ИЛИ констант с префиксом TYPE_, либо массивом, содержащим буквенные эквиваленты констант. Константы, принимаемые методом, и их буквенные эквиваленты перечислены в таблице 8.4:

Таблица 8.4. Константы типов
Константа Числовое значение Буквенный эквивалент Описание
TYPE_BOOLEAN 1 "boolean" Возвращает булевое значение как есть.
TYPE_INTEGER 2 "integer" Конвертирует integer-значение 0 в false.
TYPE_FLOAT 4 "float" Конвертирует float-значение 0.0 в false.
TYPE_STRING 8 "string" Конвертирует пустую строку '' в false.
TYPE_ZERO_STRING 16 "zero" Конвертирует строку, содержащую один символ нуля ('0') в false.
TYPE_EMPTY_ARRAY 32 "array" Конвертирует пустой массив в false.
TYPE_NULL 64 "null" Конвертирует значение null в false.
TYPE_PHP 127 "php" Конвертирует значения согласно PHP при приведении к типу boolean. (Это поведение по умолчанию.)
TYPE_FALSE_STRING 128 "false" Конвертирует строку, содержащую слово "false" в булевое false.
TYPE_LOCALIZED 256 "localized" Конвертирует локализованную строку, которая содержит определенное слово, в boolean.
TYPE_ALL 511 "all" Конвертирует все вышеперечисленные типы в boolean.

Следующий пример кода показывает два эквивалентных способа вызова метода setType():

<?php
use Zend\Filter\Boolean;

// Вызываем метод setType() и передаем ему комбинацию констант.
$filter->setType(Boolean::TYPE_BOOLEAN|
                 Boolean::TYPE_INTEGER|
                 Boolean::TYPE_STRING);

// Вызываем метод setType() и передаем ему массив буквенных эквивалентов.
$filter->setType(['boolean', 'integer', 'string']);

Метод setTranslations() позволяет определить локализованные эквиваленты булевых значений true и false. Этот принимает один параметр, который должен быть массивом в виде пар ключ=>значение, где ключ - локализованная строка, а значение - его булевое представление. Следующий пример кода показывает, как использовать метод setTranlsations():

<?php
$filter->setTranslations([
  'yes' => true,    // Английское 'да'
  'no'  => false,   // Английское 'нет'
  'ja'  => true,    // Немецкое 'да'
  'nicht' => false, // Немецкое 'нет'
  'да'  => true,    // Русское 'да'
  'нет' => false    // Русское 'нет'
  ]);

Ниже приведен фрагмент кода, демонстрирующий использование фильтра Boolean.

<?php
// Создаем фильтр Boolean.
$filter = new \Zend\Filter\Boolean();

// Настраиваем фильтр (опционально).
$filter->setCasting(true);
$filter->setType(\Zend\Filter\Boolean::TYPE_ALL);
$filter->setTranslations(['yes'=>true, 'no'=>false]);

// Фильтруем значение, приводя его к типу boolean.
$filteredValue = $filter->filter('false'); // Возвращает булевое false.
$filteredValue2 = $filter->filter('1'); // Возвращает булевое true.
$filteredValue3 = $filter->filter('false'); // Возвращает булевое false.
$filteredValue4 = $filter->filter('yes'); // Возвращает булевое true.

8.6.1.3. Фильтр ToNull

Фильтр ToNull предназначен для приведения произвольных данных к значению null, если они отвечают определенным критериям. Это может быть полезно, когда вы работаете с базой данных и хотите использовать для значения тип null вместо любого другого типа. Если значение нельзя трактовать как NULL, фильтр вернет значение как есть.

Public-методы фильтра ToNull перечислены в таблице 8.5.

Таблица 8.5. Public-методы фильтра ToNull
Имя метода Описание
filter($value) Приводит $value к null, если это возможно; иначе возвращает значение как есть.
setType($type) Определяет, какие типы нужно приводить.
getType() Возвращает определенные типы.

По умолчанию фильтр ToNull ведет себя как PHP-функция empty(): если эта функция возвращает булевое true при передаче ей входных данных, то фильтр также вернет значение null при этих данных.

Метод setType() может быть использован для задания типа, который фильтр будет приводить к null. Этот метод принимает один параметр, который может быть либо комбинацией ИЛИ констант с префиксом TYPE_, перечисленных в таблице 8.6, либо массивом их буквенных эквивалентов.

Таблица 8.6. Константы типов
Константа Числовое значение Буквенный эквивалент Описание
TYPE_BOOLEAN 1 "boolean" Конвертирует булевое значение false в null.
TYPE_INTEGER 2 "integer" Конвертирует integer-значение 0 в null.
TYPE_EMPTY_ARRAY 4 "array" Конвертирует пустой массив в null.
TYPE_STRING 8 "string" Конвертирует пустую строку '' в null.
TYPE_ZERO_STRING 16 "zero" Конвертирует строку, содержащую один символ нуля ('0') в null.
TYPE_FLOAT 32 "float" Конвертирует float-значение 0.0 в null.
TYPE_ALL 63 "all" Конвертирует все вышеперечисленные типы в null. Это поведение по умолчанию.

Следующий пример кода демонстрирует два способа вызова метода setType():

<?php
use Zend\Filter\ToNull;

// Вызываем метод setType() и передаем ему комбинацию констант.
$filter->setType(ToNull::TYPE_ZERO_STRING|Null::TYPE_STRING);

// Вызываем метод setType() и передаем ему массив буквенных эквивалентов.
$filter->setType(['zero', 'string']);

Ниже приведен фрагмент кода, показывающий, как использовать фильтр ToNull:

<?php
// Создаем фильтр ToNull.
$filter = new \Zend\Filter\ToNull();

// Настраиваем фильтр (опционально).
$filter->setType(\Zend\Filter\ToNull::TYPE_ALL);

$filteredValue = $filter->filter('0'); // Возвращает null.
$filteredValue2 = $filter->filter('1'); // Возвращает строку string '1'.
$filteredValue3 = $filter->filter(false); // Возвращает null.

8.6.1.4. Фильтр DateTimeFormatter

Фильтр DateTimeFormatter принимает дату в произвольном формате и конвертирует в желаемый формат.

Этот фильтр может принимать строку (например, '2014-03-22 15:36'), метку времени типа integer (такую, как возвращает PHP-функция time()) или экземпляр PHP-класса DateTime. Фильтр DateTimeFormatter может выбрасывать исключение Zend\Filter\Exception\InvalidArgumentException, если вы передадите ему дату в некорректном формате.

Public-методы этого фильтра перечислены в таблице 8.7.

Таблица 8.7. Public-методы фильтра DateTimeFormatter
Имя метода Описание
__construct($options) Конструктор фильтра.
filter($value) Преобразовывает дату в желаемый формат.
setFormat($format) Задает формат даты.

Во фрагменте кода ниже мы покажем, как создать фильтр, передать ему дату в виде строки и конвертировать ее в желаемый формат.

<?php
// Создаем фильтр DateTimeFormatter.
$filter = new \Zend\Filter\DateTimeFormatter();

// Задаем формат фильтра (опционально).
$filter->setFormat('F j, Y g:i A');

// Преобразовываем дату в указанный формат.
$filteredValue = $filter->filter('2014-03-22 15:36');

// Ожидаемый результат - 'March 22, 2014 3:36 PM'.

Фильтр DateTimeFormatter внутренне использует класс DateTime из стандартной библиотеки PHP для конвертации и форматирования дат. Доступные форматы дат вы можете посмотреть в документации класса DateTime.

8.6.2. Фильтры, выполняющие манипуляции с путем файла

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

8.6.2.1. Фильтр BaseName

Класс фильтра BaseName - это лишь обертка PHP-функции basename(). Он принимает строку, содержащую путь к файлу или каталогу, и возвращает последний компонент имени.

Ниже показан пример использования фильтра BaseName.

<?php
// Создаем фильтр BaseName.
$filter = new \Zend\Filter\BaseName();

// Фильтруем путь файла и возвращаем его последнюю часть.
$filteredValue = $filter->filter('/var/log/httpd/error.log');

// Ожидаемый вывод фильтра - 'error.log'.

Фильтр BaseName не будет обрабатывать нескалярное значение. Если вы передадите ему массив, он вернет его как есть и выдаст PHP-предупреждение.

8.6.2.2. Фильтр Dir

Класс фильтра BaseName - это лишь обертка PHP-функции dirname(). Он принимает строку, содержащую путь к файлу или каталогу, и возвращает путь родительского каталога.

Фильтр Dir не будет обрабатывать нескалярное значение. Если вы передадите ему массив, он вернет его как есть.

Фрагмент кода ниже демонстрирует пример использования фильтра Dir.

<?php
// Создаем фильтр Dir.
$filter = new \Zend\Filter\Dir();

// Фильтруем путь файла и возвращаем имя его каталога.
$filteredValue = $filter->filter('/var/log/httpd/error.log');

// Ожидаемый вывод фильтра - '/var/log/httpd'.

8.6.2.3. Фильтр RealPath

Фильтр RealPath принимает абсолютный или относительный путь к файлу в виде строкового аргумента. Он раскрывает все символические ссылки, переходы типа '/./', '/../' и лишние символы '/' в пути, возвращая канонизированный абсолютный путь к файлу.

Фильтр RealPath - это обертка PHP-функции realpath().

Public-методы фильтра перечислены в таблице 8.8.

Таблица 8.8. Public-методы фильтра RealPath
Имя метода Описание
__construct($options) Конструктор фильтра.
filter($value) Вовращает канонизированный абсолютный путь к файлу.
setExists($flag) Указывает, должен ли существовать путь для успешной работы фильтра. Значение true означает, что путь должен существовать; значение false означает, что можно передать несуществующий путь.
getExists() Возвращает true, если фильтруемый путь должен существовать.

Фильтр RealPath возвращает булевое false при неудаче, например, если файла не существует. Если несуществующий путь разрешен, вы можете вызвать метод setExists() с параметром false.

Фрагмент кода ниже демонстрирует пример использования фильтра RealPath.

<?php
// Создаем фильтр RealPath.
$filter = new \Zend\Filter\RealPath();

// Фильтруем путь к файлу (предполагается, что текущий
// рабочий каталог - /var/log/httpd, и что он содержит 
// файл error.log).
$filteredValue = $filter->filter('./error.log');

// Ожидаемый вывод фильтра - '/var/log/httpd/error.log'.

Фильтр RealPath не будет обрабатывать нескалярное значение. Если вы передадите ему массив, он вернет его как есть.

8.6.3. Фильтры, осуществляющие сжатие и шифрование входных данных

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

8.6.3.1. Фильтр Compress

Фильтр Compress предназначен для сжатия входных данных с помощью некоторого алгоритма сжатия. Например, этот фильтр можно использовать, чтобы сжать данные и сохранить их в виде архива.

Public-методы фильтра перечислены в таблице 8.9.

Таблица 8.9. Public-методы фильтра Compress
Имя метода Описание
__construct($options) Конструктор фильтра.
filter($value) Производит сжатие данных, используя указанный алгоритм.
getAdapter() Возвращает текущий адаптер, инстанцируя его, если необходимо.
getAdapterName() Извлекает имя адаптера.
setAdapter($adapter) Задает адаптер сжатия.
getAdapterOptions() Извлекает опции адаптера.
setAdapterOptions($options) Задает опции адаптера.
getOptions($option) Получает отдельную или все опции используемого адаптера.

Сам фильтр Compress не может сжимать данные. Вместо этого он использует так называемый класс адаптера. Класс адаптера должен реализовывать интерфейс CompressionAlgorithmInterface. Вы добавляете адаптер к фильтру Compress, и адаптер реализует определенный алгоритм сжатия.

Существует несколько стандартных классов адаптеров (см. рисунок 8.2 и таблицу 8.10). Эти классы "живут" в пространстве имен Zend\Filter\Compress.

Таблица 8.10. Адаптеры сжатия
Class name Description
Bz2 Bzip2 - алгоритм сжатия Барроуза-Уилера.
Gz Алгоритм сжатия Gzip основан на алгоритме Deflate, являющимся комбинацией алгоритма LZ77 и кодирования Хаффмана.
Zip ZIP - алгоритм сжатия, широко используемый в операционной системе Windows.
Tar
Lzf LZF - очень быстрый алгоритм сжатия, идеальный для экономии пространства без большого ущерба для скорости.
Snappy Snappy - основанная на идея LZ77 библиотека для быстрого сжатия и распаковки данных, разработанная Google.
Rar RAR - формат архива, поддерживающий сжатие данных, устранение ошибок и разделение одного файла на несколько.

Рисунок 8.2. Наследование адаптеров алгоритмов сжатия Рисунок 8.2. Наследование адаптеров алгоритмов сжатия

Фрагмент кода ниже демонстрирует пример использования фильтра Compress.

<?php
// Создаем фильтр Compress.
$filter = new \Zend\Filter\Compress();

// Настраиваем адаптер.
$filter->setAdapter('Zip');
$filter->setAdapterOptions([
        'archive' => 'example.zip',
    ]);

// Сжимаем входные данные (предполагается, что в текущем рабочем каталоге 
// находится файл testfile.txt ).
$filter->filter('testfile.txt');

В примере выше мы создаем экземпляр фильтра @`Compress (строка 3), задаем его адаптер (строка 6), задаем опции адаптера (строка 7) и затем сжимаем входной файл (строка 13). Ожидаемый результат, файл архива example.zip, будет создан в текущем каталоге. Архив будет содержать файл testfile.txt.

Фильтр Decompress является "зеркальным отражением" фильтра Compress и используется аналогично. По этой причине мы не будем рассматривать фильтр Decompress в этом разделе.

8.6.3.2. Фильтр Encrypt

Задача фильтра Encrypt - шифрование входных данных с помощью указанного алгоритма. Public-методы фильтра перечислены в таблице 8.11.

Таблица 8.11. Public-методы фильтра Encrypt
Имя метода Описание
__construct($options) Конструктор фильтра.
filter($value) Производит шифрование данных, используя указанный алгоритм.
getAdapter() Возвращает текущий адаптер, инстанцируя его, если необходимо.
setAdapter($adapter) Задает адаптер сжатия.

Фильтр Encrypt использует классы адаптеров для непосредственной шифровки данных. Вы добавляете адаптер к фильтру Encrypt[Zend\Filter\Encrypt] с помощью метода setAdapter(), и адаптер производит определенное шифрование. Класс адаптера должен реализовывать интерфейс EncryptionAlgorithmInterface.

Существует несколько стандартных классов адаптеров (см. рисунок 8.3). Эти классы "живут" в пространстве имен Zend\Filter\Encrypt.

Рисунок 8.3. Наследование адаптеров алгоритмов шифрования Рисунок 8.3. Наследование адаптеров алгоритмов шифрования

Фрагмент кода ниже демонстрирует пример использования фильтра Encrypt.

<?php
// Создаем фильтр Encrypt.
$filter = new \Zend\Filter\Encrypt();

// Задаем адаптер шифрования.
$filter->setAdapter('BlockCipher');

// Зашифровываем входные данные.
$filteredValue = $filter->filter('some data to encrypt');

Ожидаемые результат - строка, зашифрованная блочным шифром.

Фильтр Decrypt является "зеркальным отражением" фильтра Encrypt и используется аналогично. По этой причине мы не будем рассматривать фильтр Decrypt в этом разделе.

8.6.4. Фильтры, управляющие строковыми данными

В этом разделе мы рассмотрим примеры использования фильтров из группы фильтров, связанных с изменением строковых данных.

8.6.4.1. Фильтр StringToLower

Класс фильтра StringToLower предназначен для преобразования входных строковых данных в символы нижнего регистра. Public-методы фильтра представлены ниже в таблице 8.12.

Таблица 8.12. Public-методы фильтра StringToLower
Имя метода Описание
__construct($options) Конструктор фильтра.
filter($value) Конвертирует строку в нижний регистр.
setEncoding($encoding) Задает кодировку входных данных для заданной строки.
getEncoding() Возвращает кодировку.

По умолчанию, фильтр работает как PHP-функция strtolower(). Принимая строковое значение, он возвращает строку, в которой все буквенные символы переведены в нижний регистр. Принадлежность символа к "буквенным" определяется локалью системы. Это значит, что, например, в стандартной локали "C" такие символы, как «а-умлаут» (Ä) не будут конвертированы.

Вызов метода setEncoding() на фильтре и передача ему кодировки принуждает фильтр вести себя как PHP-функция mb_strtolower(). В отличие от strtolower() то, что символ является буквой, определяется свойствами символа Юникода. Поэтому поведение этой функции не зависит от настроек локали, и она может конвертировать любой символ, определяемый в Юникоде как "буква", например, «а-умлаут» (Ä).

Если представленное значение нескалярное, оно останется неотфильтрованным, и будет выдано предупреждение E_USER_WARNING, указывающее на то, что значение не может быть отфильтровано.

Фрагмент кода ниже показывает, как использовать фильтр Encrypt:

<?php
// Создаем фильтр StringToLower.
$filter = new \Zend\Filter\StringToLower();

// Задаем кодировку для фильтра (опционально).
$filter->setEncoding('UTF-8');

// Фильтруем строку.
$filteredValue = $filter->filter('How to Start a Business in 10 Days');

// Ожидаемый вывод фильтра - 'how to start a business in 10 days'.

Фильтр StringToUpper (перед строки в верхний регистр) является "зеркальным отражением" фильтра StringToLower и используется аналогично. По этой причине мы не будем рассматривать фильтр StringToUpper в этом разделе.

8.6.4.2. Фильтр PregReplace

Фильтр PregReplace может быть использован для поиска и замены строковых данных по регулярному выражению. Этот фильтр - обертка PHP-функции preg_replace(). Public-методы этого фильтра представлены ниже в таблице 8.13.

Таблица 8.13. Public-методы фильтра PregReplace
Имя метода Описание
__construct($options) Конструктор фильтра.
filter($value) Выполняет поиск и замену по регулярному выражению.
setPattern($pattern) Задает искомый шаблон. Это может быть либо строка, либо массив строк.
getPattern() Возвращает шаблон.
setReplacement($replacement) Задает строку или массив строк, используемые в качестве замены.
getReplacement() Получает установленное в данный момент значение замены.

Фрагмент кода ниже показывает, как использовать фильтр PregReplace:

<?php
// Создаем фильтр PregReplace.
$filter = new \Zend\Filter\PregReplace();

// Настраиваем фильтр.
$filter->setPattern("/\s\s+/");
$filter->setReplacement(' ');

// Фильтруем строку.
$filteredValue = $filter->filter('An example    with    multiple     spaces.');

// Ожидаемый вывод фильтра - 'An example with multiple spaces.'

8.6.4.3. Фильтр StripTags

Фильтр StripTags удаляет все теги (например, <!-- -->, <p>, <h1> или <?php ?>) из входной строки. Он также позволяет явно определить теги, которые не должны быть удалены. Кроме этого, фильтр предоставляет возможность указать, какие атрибуты всех и/или только определенных тегов разрешены.

Public-методы фильтра StripTags перечислены в таблице 8.14.

Таблица 8.14. Public-методы фильтра StripTags
Имя метода Описание
__construct($options) Конструктор фильтра.
filter($value) Возвращает значение, из которого удалены теги.
getAttributesAllowed() Возвращает список разрешенных атрибутов тегов.
setAttributesAllowed($attributesAllowed) Задает список разрешенных атрибутов тегов.
getTagsAllowed() Возвращает список разрешенных тегов.
setTagsAllowed($tagsAllowed) Задает список разрешенных тегов.

Фрагмент кода ниже показывает, как использовать фильтр StripTags:

<?php
// Создаем фильтр StripTags.
$filter = new \Zend\Filter\StripTags();

// Настраиваем фильтр.
$filter->setTagsAllowed(['p']);

// Фильтруем строку.
$filteredValue = $filter->filter(
  '<p>Please click the following <a href="example.com">link</a>.</p>');

// Ожидаемый вывод фильтра - 
// '<p>Please click the following link.</p>;'

StripTags не будет обрабатывать нескалярное значение. Если передать фильтру такое значение, оно останется неотфильтрованным.

8.6.4.4. Фильтр StripNewlines

StripNewlines` - весьма простой фильтр, который возвращает входную строку без символов перевода строки ("\r", "\n").

Фрагмент кода ниже показывает, как использовать фильтр StripNewlines:

<?php
// Создаем фильтр StripNewlines.
$filter = new \Zend\Filter\StripNewlines();

// Фильтруем строку.
$filteredValue = $filter->filter("A multi line\r\n string");

// Ожидаемый вывод фильтра - 'A multi line string'.

StripNewlines не будет обрабатывать нескалярное значение. Если передать фильтру такое значение, оно останется неотфильтрованным.

8.6.4.5. Фильтр UriNormalize

Фильтр UriNormalize может использоваться для нормализации URL-строки и (опционально) применения к ней схемы. Public-методы этого фильтра приведены ниже в таблице 8.15.

Таблица 8.15. Public-методы фильтра UriNormalize
Имя метода Описание
filter($value) Фильтрует URL, нормализуя его и применяя схему по умолчанию (если она задана).
setDefaultScheme($defaultScheme) Задает схему по умолчанию для использования при разборе URI, не имеющим схем.
setEnforcedScheme($enforcedScheme) Задает схему для применения к URI, не имеющим схем.

Процедура нормализации URL, как правило, состоит из следующих шагов:

  1. Строка URL разбивается на части: схему, хост, номер порта, путь и запрос. Если у заданного URL нет схемы, используется схема по умолчанию.
  2. Части схемы и хоста переводятся в нижний регистр.
  3. Номер порта сверяется со списком разрешенных номеров, и, если он не принадлежит этому списку, номер порта убирается.
  4. Путь URL фильтруется: удаляются лишние сегменты точек, декодируются любые URL-закодированные символы, а также URL-кодируется все, что должно быть закодировано.
  5. Часть запроса очищается: URL-декодируется все, что не должно быть закодированным и URL-кодируется все остальное.

Правила нормализации URL могут отличаться для разных протоколов (схем). Если URL не содержит часть схемы, по умолчанию присваивается схема http. Вы можете использовать метод setDefaultScheme() фильтра UriNormalize, чтобы установить схему по умолчанию для нормализации URL. Он принимает любую из следующих схем: http, https, file, mailto, urn и tag`.

Кроме того, другой метод фильтра @UriNormalize, setEnforcedScheme()`, позволяет переопределить схему по умолчанию так называемой "принудительной" схемой, если заданный URL не имеет части схемы.

Фрагмент кода ниже показывает, как использовать фильтр UriNormalize:

<?php
// Создаем фильтр UriNormalize.
$filter = new \Zend\Filter\UriNormalize();

// Настраиваем фильтр.
$filter->setDefaultScheme('http');
$filter->setEnforcedScheme('https');

// Фильтруем URL-строку.
$filteredValue = $filter->filter('www.example.com');

// Ожидаемый вывод фильтра - 'https://www.example.com/'.

8.6.5. Организация фильтров в цепь

Фильтры могут быть организованы в последовательность. Это можно сделать с помощью класса FilterChain. При запуске подобного составного фильтра, значение, отфильтрованное первым фильтром передается второму в качестве входных данных, затем значение, отфильтрованное вторым фильтром передается третьему и так далее.

Класс FilterChain[Zend\Filter\FilterChain] внутренне используется классом-контейнером InputFilter для хранения последовательности фильтров, присоединенных к полю модели формы.

Public-методы, предоставляемые классом FilterChain, представлены в таблице 8.16:

Таблица 8.16. Public-методы фильтра FilterChain
Имя метода Описание
filter($value) Возвращает значение, отфильтрованное каждым фильтром цепи. Фильтры запускаются в том же порядке, в котором были добавлены в цепь (FIFO - «первым пришёл — первым ушёл»).
setOptions($options) Задает опции.
attach($callback, $priority) Добавляет к цепи существующий экземпляр фильтра (или функцию обратного вызова).
attachByName($name, $options, $priority) Инстанцирует фильтр по имени класса или псевдониму и вставляет его в цепь.
merge($filterChain) Объединяет одну цепочку фильтров с другой.
getFilters() Возвращает все присоединенные фильтры
count() Возвращает количество присоединенных фильтров.

Пример цепочки фильтров показан на рисунке 8.4. Она состоит из фильтра StringTrim, за которым идет фильтр StripTags, за которым в свою очередь следует фильтр StripNewlines.

Рисунок 8.4. Цепь фильтров Рисунок 8.4. Цепь фильтров

Для создания цепочки как на рисунке 8.4 мы используем следующий код:

<?php
use Zend\Filter\FilterChain;

// Инстанцируем цепь фильтров.
$filter = new FilterChain();

// Вставляем фильтры в цепочку.
$filter->setOptions([
    'filters'=>[
        [
            'name'=>'StringTrim',
            'options'=>['charlist'=>"\r\n\t "],
            'priority'=>FilterChain::DEFAULT_PRIORITY
        ],
        [
            'name'=>'StripTags',
            'options'=>['tagsallowed'=>['p']],
            'priority'=>FilterChain::DEFAULT_PRIORITY
        ],
        [
            'name'=>'StripNewlines',
            'priority'=>FilterChain::DEFAULT_PRIORITY
        ]
    ]
]);

// Выполняем все фильтры в цепи.
$filteredValue = $filter->filter("  name@example.com<html>\n ");

// Ожидаемый вывод - 'name@example.com'.

В этом фрагменте первым делом мы инстанцируем фильтр FilterChain с помощью оператора new (строка 5). В строке 8 мы задаем конструкцию цепочки фильтров методом setOptions().

Этот метод принимает описание в виде массива, подобно методу add() класса InputFilter. Массив имеет ключ "filters", где вы можете зарегистрировать фильтры, которые хотите присоединить к цепи. Для каждого добавленного фильтра нужно предоставить следующие подключи:

Наконец, в строке 28 мы вызываем метод filter(), который проходит по цепи и передает фильтруемое значение каждому фильтру по очереди.

8.6.6. Пользовательская фильтрация с помощью фильтра Callback

Стандартные фильтры предназначены для использования в часто встречающихся ситуациях. Например, вам часто может понадобиться убрать пробелы из начала и конца строки или преобразовать ее в нижний регистр. Однако, иногда могут возникнуть случаи, когда вы не можете использовать стандартный фильтр. В таких ситуациях удобно пользоваться фильтром Callback.

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

Пользовательский алгоритм фильтрации реализуется как функция обратного вызова или метод класса обратного вызова. Механизм обратного вызова (callback) - это функция или public-метод класса, вызываемый фильтром Callback, принимающий значение, которое нужно отфильтровать, и (опционально) аргумент(ы), определяемый(-е) пользователем.

Public-методы, предоставляемые фильтром Callback перечислены в таблице 8.17.

Table 8.17. Public-методы фильтра Callback
Имя класса Описание
filter($value) Выполняет функцию обратного вызова в качестве фильтра.
setCallback($callback) Задает новый механизм обратного вызова для данного фильтра.
getCallback() Возвращает установленный для фильтра механизм обратного вызова.
setCallbackParams($params) Задает параметры для механизма обратного вызова.
getCallbackParams() Получает параметры для механизма обратного вызова.

Как видите из таблицы, фильтр Callback предоставляет методы setCallback() и setCallbackParams(), которые можно использовать для задания функции обратного вызова (или метода класса обратного вызова) и, возможно, передать ей один или несколько параметров.

8.6.6.1. Пример

Чтобы продемонстрировать использование фильтра Callback, присоединим поле номера телефона к нашему классу модели формы обратной связи (ContactForm) и добавим к нему пользовательский фильтр.

Международный телефонный номер обычно выглядит как "1 (808) 456-7890". Он содержит код страны, за которым следует код области из трех цифр, заключенных в скобки. Оставшаяся часть номера состоит из семизначного кода абонента, разделенного на две группы символом тире. Код страны, код области и код абонента разделены пробелами. В дальнейшем мы будем называть этот телефонный формат "международным" форматом.

Международный телефонный формат необходим для совершения звонков между странами (или областями). Если звонки делаются внутри одной и той же области, номер телефона может выглядеть как просто "456-7890" (код страны и код области просто опускаются). Такой формат мы будем называть "локальным" телефонным форматом.

Чтобы сделать наш фильтр как можно более универсальным, предположим, что пользователю необходимо ввести номер в международном формате в одни формы и в локальном формате в другие. Так как некоторые посетители сайта могут ввести свой телефонный номер в формате, отличном от требуемого, мы хотим применить фильтр, который будет "нормализовывать" для нас номер.

Чтобы сделать "нормализацию" номера, фильтр:

  1. Уберет все нечисловые символы из входного значения.
  2. Дополнит значение цифрами до необходимой длины, если цифр слишком мало.
  3. Добавит скобки, пробелы и тире (при использовании международного формата); или просто тире (при использовании локального формата).

Так как ZF3 не предоставляет стандартных фильтров для выполнения подобной операции фильтрации номера, мы используем фильтр-обертку Callback. Для этого мы внесем следующие изменения в код нашего класса ContactForm:

<?php
// ...
class ContactForm extends Form
{
  // ...
  protected function addElements() 
  {
    // ...            
        
    // Добавляем поле "phone"
    $this->add([
        'type'  => 'text',
        'name' => 'phone',
        'attributes' => [                
           'id' => 'phone'
        ],
        'options' => [
           'label' => 'Your Phone',
        ],
     ]);
  }
    
  private function addInputFilter() 
  {
    // ...    
    $inputFilter->add([
        'name'     => 'phone',
        'required' => true,
        'filters'  => [                    
          [
            'name' => 'Callback',
            'options' => [
              'callback' => [$this, 'filterPhone'],
              'callbackParams' => [
                'format' => 'intl'
              ]
            ]                        
          ],
        ],                                
      ]);
  }
    
  // Пользовательский фильтр для номера телефона.
  public function filterPhone($value, $format) 
  {
    if(!is_scalar($value)) {
      // Возвращаем нескалярное значение нефильтрованным.
      return $value;
    }
            
    $value = (string)$value;
        
    if(strlen($value)==0) {
      // Возвращаем пустое значение нефильтрованным.
      return $value;
    }
        
    // Сначала удаляем все нечисловые символы.
    $digits = preg_replace('#[^0-9]#', '', $value);
        
    if($format == 'intl') {            
      // Дополняем нулями, если число цифр некорректно.
      $digits = str_pad($digits, 11, "0", STR_PAD_LEFT);

      // Добавляем скобки, пробелы и тире.
      $phoneNumber = substr($digits, 0, 1) . ' ('.
                     substr($digits, 1, 3) . ') ' .
                     substr($digits, 4, 3) . '-'. 
                     substr($digits, 7, 4);
    } else { // 'local'
      // Дополняем нулями, если число цифр некорректно.
      $digits = str_pad($digits, 7, "0", STR_PAD_LEFT);

      // Добавляем тире.
      $phoneNumber = substr($digits, 0, 3) . '-'. substr($digits, 3, 4);
    }
        
    return $phoneNumber;               
  }
}

В строках 11-20 вышеприведенного фрагмента мы добавляем поле "phone" к модели формы ContactForm. Это поле является обычным текстовым полем ввода, и у нас уже был опыт работы с такими полями.

Затем, в строках 26-40 мы добавляем правило валидации для поля "phone" нашей формы. Под ключом "filters" (строка 29) мы регистрируем фильтр Callback (в данном случае мы используем псевдоним Callback, но вы можете вместо этого воспользоваться полностью определенным именем класса Callback::class).

Фильтр принимает две опции: "callback" и "callback_params". Опция "callback" - это массив, состоящий из двух элементов, которые представляют соответственно класс и метод, который нужно вызвать. В этом примере, механизмом обратного вызова является метод filterPhone() класса ContactForm. Параметр "format" передается методу обратного вызова с помощью опции "callbackParams (строка 34).

В строках 44-79 мы определяем метод обратного вызова filterPhone(), принимающий два аргумента: $value - номер телефона, который нужно отфильтровать и $format - желаемый формат номера. Параметр $format может быть либо local (для локального формата), либо intl (для международного).

В методе обратного действия filterPhone() мы делаем следующее:

Чтобы посмотреть, как работает этот фильтр, можете открыть URL "http://localhost/contactus" в своем браузере. Если вы введете какой-либо номер телефона в некорректном формате, фильтр исправит номер и преобразует его в желаемый формат.


Top