YiiConf 2017 всё ближе! Не забудьте купить билет.

Использование собственных фильтров в правилах валидации

Фильтры — очень полезная и мощная возможность Yii. Покажем, как создать
и применить свой фильтр для транслитерирования поля модели (то есть «абаба
галамага» превратить в «ababa_galamaga»).

Опишем класс нашего фильтра TranslitFilter. В нём создадим метод translitUrl,
который будет обрабатывать наше поле. Для транислитерации существует множество
различных правил и стандартов. В примере ниже использован немного изменённый код
http://programmerz.ru/post/php_translit.html:

class TranslitFilter {
    public function translitUrl($str){
        $tr = array(
          "А"=>"a","Б"=>"b","В"=>"v","Г"=>"g",
          "Д"=>"d","Е"=>"e","Ж"=>"j","З"=>"z","И"=>"i",
          "Й"=>"y","К"=>"k","Л"=>"l","М"=>"m","Н"=>"n",
          "О"=>"o","П"=>"p","Р"=>"r","С"=>"s","Т"=>"t",
          "У"=>"u","Ф"=>"f","Х"=>"h","Ц"=>"ts","Ч"=>"ch",
          "Ш"=>"sh","Щ"=>"sch","Ъ"=>"","Ы"=>"yi","Ь"=>"",
          "Э"=>"e","Ю"=>"yu","Я"=>"ya","а"=>"a","б"=>"b",
          "в"=>"v","г"=>"g","д"=>"d","е"=>"e","ж"=>"j",
          "з"=>"z","и"=>"i","й"=>"y","к"=>"k","л"=>"l",
          "м"=>"m","н"=>"n","о"=>"o","п"=>"p","р"=>"r",
          "с"=>"s","т"=>"t","у"=>"u","ф"=>"f","х"=>"h",
          "ц"=>"ts","ч"=>"ch","ш"=>"sh","щ"=>"sch","ъ"=>"y",
          "ы"=>"yi","ь"=>"","э"=>"e","ю"=>"yu","я"=>"ya",
          " "=> "_", "."=> "", "/"=> "_"
        );

        if (preg_match('/[^A-Za-z0-9_\-]/', $str)) {
          $str = strtr($str,$tr);
          $str = preg_replace('/[^A-Za-z0-9_\-]/', '', $str);
        }

        return $str;
    }
}

Сохраняем его под этим же именем в директории, доступной для импорта. Далее в методе
rules модели прописываем следующее:

return array(
    // …
    array('alias', 'filter', 'filter'=>array("TranslitFilter", "translitUrl")),
)

Info|Информация: в filter указывается функция обратного вызова в виде
array("Класс", "метод"). При использовании метода того же контроллера
в качестве имени указывается $this.

Для версий 1.0.x не забываем прописать нужное поле в safeAttributes().

Таким же образом можно использовать любой метод любого существующего компонента.
Например, вот так можно выполнить фильтрацию текста от XSS-атак:

public function rules() {
    return array(
        array('text','required'),
        array('text','filter','filter'=>array($obj=new CHtmlPurifier(),'purify')),
        //тут какие-то правила…
        array('time','default','value'=>time()),
    );
}