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

Обсуждение документации. Переводы Cookbook и авторские рецепты.
Ответить
Dreammaker
Сообщения: 139
Зарегистрирован: 2009.09.02, 16:21
Откуда: Черкассы, Украина

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

Сообщение Dreammaker »

Понадобилось мне сделать транслитерацию поля для использования его в генерации урла, то есть "абаба галамага" превратить в "ababa_galamaga". Решением для этого является использование механизма фильтров основанный на CFilterValidator . Но, не сразу мне стало понятно, как использовать собственные фильтры, в отличие от встроенных в пхп функций типа trim.

Но на самом деле всё просто. Первым делом создадим класс c названием, например, DCustomFilters ( я свои классы начинаю с D :) ), в нём создаём метод, который будет обрабатывать переменную. В моём случае я взял нашедшийся через гугл код http://programmerz.ru/post/php_translit.html и немного изменил его. В итоге получился вот такой класс:

Код: Выделить всё

class DCustomFilters
{

        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("DCustomFilters", "translitUrl")),
) 
не забываем прописать нужное поле в safeAttributes (для версии 1.0, в 1.1 насколько я понял надобности в этом нет).

Всё, поле транслитерируется. :)
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

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

Сообщение samdark »

Очень полезный рецепт. Добавил в немного видоизменённом варианте в сборник: http://yiiframework.ru/doc/cookbook/ru/ ... ion.fiters
Ekstazi
Сообщения: 1428
Зарегистрирован: 2009.08.20, 22:54
Откуда: Молдова, Бельцы
Контактная информация:

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

Сообщение Ekstazi »

Вот пример для использования htmlpurifier:

Код: Выделить всё

    public function rules()
    {
        return array(
                        array('text','required'),
                        array('text','filter','filter'=>array($obj=new CHtmlPurifier(),'purify')),
//тут какие-то правила ....
                        array('time','default','value'=>time()),
        );
    }
 
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

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

Сообщение samdark »

Добавил в конец рецепта.
Ekstazi
Сообщения: 1428
Зарегистрирован: 2009.08.20, 22:54
Откуда: Молдова, Бельцы
Контактная информация:

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

Сообщение Ekstazi »

Эм, Sam, а ты не мог бы добавить в статью:
# Дополнения: Ekstazi
:oops:
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

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

Сообщение samdark »

Готово.
MrCherry
Сообщения: 44
Зарегистрирован: 2010.02.18, 14:14

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

Сообщение MrCherry »

фуф.. что-то ну никак не могу понять, как при таком использовании забивать конфигурацию в HtmlPurifier:
array('text','filter','filter'=>array($obj=new CHtmlPurifier(),'purify')),
MrCherry
Сообщения: 44
Зарегистрирован: 2010.02.18, 14:14

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

Сообщение MrCherry »

кхм.. нигде не написано нужного способа, подключал прям так.. "в лоб"

в конфиге:

Код: Выделить всё

'preload' => array('log','htmlpurifier'), //htmlpurifier надо в preload добавить, иначе он всё рушит..     

потом в массив компонентов добавить элемент:

Код: Выделить всё

'htmlpurifier' => array(
         'class' => 'CHtmlPurifier',
         'options'=> array(
         'HTML.TidyLevel'=>'heavy',
        'HTML.AllowedElements'=>'a,b'
     ),
), 

теперь в правилах валидации можно бацать фильтр:

Код: Выделить всё

array('description','filter', 'filter' => array(Yii::app()->htmlpurifier,'purify')), //очистка поля description   
Ну и в своём коде можно:

Код: Выделить всё

echo Yii::app()->htmlpurifier->purify('<script>alert(00);</script><br/>dcs<b>dcs</b>');//Вырежет [b]<script>[/b], [b]<br/>[/b]. А [b]<b>[/b] оставит.     
Ссылочка на документацию по конфигурации HtmlPurifier - http://htmlpurifier.org/live/configdoc/plain.html
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

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

Сообщение samdark »

http://www.yiiframework.com/doc/api/CHtmlPurifier
Можно использовать компонент:

Код: Выделить всё

$p = new CHtmlPurifier();
$p->options = array('URI.AllowedSchemes'=>array(
  'http' => true,
  'https' => true,
  'mailto' => true,
  'ftp' => true,
  'nntp' => true,
  'news' => true,
  )
);
$text = $p->purify($text);
 
Также можно использовать как фильтр контроллера, но очень не рекомендуется т.к. производительность HtmlPurifier не сильно высокая.
MrCherry
Сообщения: 44
Зарегистрирован: 2010.02.18, 14:14

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

Сообщение MrCherry »

ну так то оно само собой. а вот как опции передать в правила валидации.
однако, спасибо за мысль. я что то туплю, нафик не надо его в правила валидации пихать :D
andry
Сообщения: 224
Зарегистрирован: 2009.11.08, 16:52

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

Сообщение andry »

хотел уточнить по поводу CHtmlPurifier, мне нужно допустим отфильтровать при сохранении несколько полей, к примеру текcт и заголовок, получается нужно под каждое поле создавать отдельный объект для каждого поля?

Например поле Текст

Код: Выделить всё

$p_text = new CHtmlPurifier();
$p_text->options = array(
 'HTML.AllowedElements'=>'a,img,i,b,u,s,em,strong,li,ol,ul,sup,abbr,sub,acronym,h4,h5,h6,br,hr,pre,p,div,code,blockquote',
);
$text = $p_text->purify($text);  
Поле Заголовок

Код: Выделить всё

$p_title = new CHtmlPurifier();
$p_title->options = array(
 'HTML.AllowedElements'=>'b',
);
$title = $p_title->purify($title); 
всё верно?
ведь одно правило описываемое в конфиге нельзя совмещать для разных полей, у каждого свои правила, к примеру у заголовка нельзя использовать те теги что у поля под текст
Ekstazi
Сообщения: 1428
Зарегистрирован: 2009.08.20, 22:54
Откуда: Молдова, Бельцы
Контактная информация:

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

Сообщение Ekstazi »

По идее можно и один объект использовать:

Код: Выделить всё

    $p_text = new CHtmlPurifier();
    $p_text->options = array(
     'HTML.AllowedElements'=>'a,img,i,b,u,s,em,strong,li,ol,ul,sup,abbr,sub,acronym,h4,h5,h6,br,hr,pre,p,div,code,blockquote',
    );
    $text = $p_text->purify($text);  
    $p_text->options = array(
     'HTML.AllowedElements'=>'b',
    );
    $title = $p_text->purify($title); 
 
parxtan
Сообщения: 6
Зарегистрирован: 2011.08.24, 10:10

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

Сообщение parxtan »

а как передать параметр в функцию транслита?

array('alias', 'filter', 'filter'=>array("DCustomFilters", "translitUrl")),

- к примеру чтобы в alias заносился транслит значения поля title
Flicker
Сообщения: 15
Зарегистрирован: 2010.12.21, 12:17

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

Сообщение Flicker »

parxtan писал(а):а как передать параметр в функцию транслита?

array('alias', 'filter', 'filter'=>array("DCustomFilters", "translitUrl")),

- к примеру чтобы в alias заносился транслит значения поля title
я лично сделал так :
- убрал из rules filter
- в контроллере перед

Код: Выделить всё

$model->attributes=$_POST['Category']; 
вставил

Код: Выделить всё

$_POST['Category']['alias'] = TranslitFilter::translitUrl((string)$_POST['Category']['title']); 
насколько это правильно не знаю, но работает
Ответить