Yii: Транслитерация URL-адреса (автоматическое создание псевдонима для url из заголовка)

Yii: Транслитерация URL-адреса (автоматическое создание псевдонима для url из заголовка) Рассмотрим как сделать, чтобы псевдоним для url-адреса автоматически создавался из содержимого поля заголовка (title). Причём так, чтобы оставалась возможность при желании его отредактировать

Взял за основу расширение из yiiext (translit-filter), но добавил преобразование всех символов в нижний регистр и поменял некоторые замены.

1) Создаём в protected/extensions новый файл LocoTranslitFilter.php с содержимым

<?php
/**
 * ETranslitFilter class file reworked to Loco version: LocoTranslitFilter.
 *
 * @author Veaceslav Medvedev <slavcopost@gmail.com> then almix
 * @link http://code.google.com/p/yiiext/
 * @license http://www.opensource.org/licenses/mit-license.php
 */
class LocoTranslitFilter extends CValidator
{
        /**
         * @var string the name of the attribute to be translit.
         */
        public $translitAttribute;
        /**
         * @var boolean whether to translit value only when the attribute value is null or empty string.
         * Defaults to true. If false, the attribute will always be translit.
         */
        public $setOnEmpty=true;

        /**
         * Validates the attribute of the object.
         * @param CModel $object the object being validated
         * @param string $attribute the attribute being validated
         */
        protected function validateAttribute($object,$attribute)
        {
                if($this->setOnEmpty && !$this->isEmpty($object->$attribute))
                        return;

                if(!$object->hasAttribute($this->translitAttribute))
                        throw new CException(Yii::t('yiiext','Active record "{class}" is trying to select an invalid column "{column}". Note, the column must exist in the table or be an expression with alias.',
                                array('{class}'=>get_class($object),'{column}'=>$this->translitAttribute)));
                

                $object->$attribute=self::cyrillicToLatin($object->getAttribute($this->translitAttribute));
        }
        /**
         * Translit text from cyrillic to latin letters.
         * @static
         * @param string $text the text being translit.
         * @return string
         */
        protected static function cyrillicToLatin($text, $toLowCase = TRUE)
        {
                $matrix=array(
                        "й"=>"i","ц"=>"c","у"=>"u","к"=>"k","е"=>"e","н"=>"n",
                        "г"=>"g","ш"=>"sh","щ"=>"shch","з"=>"z","х"=>"h","ъ"=>"",
                        "ф"=>"f","ы"=>"y","в"=>"v","а"=>"a","п"=>"p","р"=>"r",
                        "о"=>"o","л"=>"l","д"=>"d","ж"=>"zh","э"=>"e","ё"=>"e",
                        "я"=>"ya","ч"=>"ch","с"=>"s","м"=>"m","и"=>"i","т"=>"t",
                        "ь"=>"","б"=>"b","ю"=>"yu",
                        "Й"=>"I","Ц"=>"C","У"=>"U","К"=>"K","Е"=>"E","Н"=>"N",
                        "Г"=>"G","Ш"=>"SH","Щ"=>"SHCH","З"=>"Z","Х"=>"X","Ъ"=>"",
                        "Ф"=>"F","Ы"=>"Y","В"=>"V","А"=>"A","П"=>"P","Р"=>"R",
                        "О"=>"O","Л"=>"L","Д"=>"D","Ж"=>"ZH","Э"=>"E","Ё"=>"E",
                        "Я"=>"YA","Ч"=>"CH","С"=>"S","М"=>"M","И"=>"I","Т"=>"T",
                        "Ь"=>"","Б"=>"B","Ю"=>"YU",
                        "«"=>"","»"=>""," "=>"-",

"\""=>"", "\."=>"", "–"=>"-", "\,"=>"", "\("=>"", "\)"=>"",
"\?"=>"", "\!"=>"", "\:"=>"",

'#' => '', '№' => '',' - '=>'-', '/'=>'-', '  '=>'-',
                );
                
                // Enforce the maximum component length
		$maxlength = 100;                                  
		$text = implode(array_slice(explode('<br>',wordwrap(trim(strip_tags(html_entity_decode($text))),$maxlength,'<br>',false)),0,1));
		//$text = substr(, 0, $maxlength); 

                foreach($matrix as $from=>$to)
                        $text=mb_eregi_replace($from,$to,$text); 

// Optionally convert to lower case.
       if ($toLowCase) 
       {
           $text = strtolower($text);
       }  

                return $text;
        }
}

2) Добавляем правило для псевдонима (тут – alias) в массиве rules() в нужной модели

array('alias','ext.LocoTranslitFilter','translitAttribute'=>'title'), 

В переменной translitAttribute указываем поле в таблице (атрибут в модели), который будет транслитерироваться. Таким образом при создании или редактировании формы будет происходить транслитерация заголовка для url-адреса в 'alias'. 

Кроме того в функции validateAttribute есть проверка, заполнено ли поле псевдонима уже или пустое, и в случае если уже заполнено, то не выполнять транслитерацию. Это полезно, если вы хотите вручную прописать псевдоним. Так он при повторном редактировании не перезапишется.

Источник: loco.ru

almix
Разработчик Loco, автор статей по веб-разработке на Yii, CodeIgniter, MODx и прочих инструментах. Создатель Team Sense.

Вы можете почитать все статьи от almix'а.



Другие статьи по этой теме:

Комментарии (7)     Подпишитесь на RSS комментариев к этой статье.

7 комментариев

#712
Виталий говорит:
November 25, 2012 at 02:25 pm

Здравствуйте. Сделал все как написано в статье но в итоге получаю ошибку "Не определено свойство "LocoTranslitFilter.title"."

После создания LocoTranslitFilter.php в файле модели (Awards.php) в rules() я дописал такую строку:

array('alias','ext.LocoTranslitFilter','title'=>'alias'),

alias - это поле в бд и лейбл поля. title это поле которое будет транслетерироваться в поле alias. Подскажите в чем проблема. Уже намучался с ней.

#713
almix говорит:
November 27, 2012 at 01:00 am
Виталий, неправильно дописали строку!!
надо оставить - array('alias','ext.LocoTranslitFilter','translitAttribute'=>'title'), translitAttribute = это параметр, то есть имя переменной из созданного нами расширения LocoTranslitFilter, не заменяйте её на title!
#884
guest говорит:
May 28, 2013 at 11:08 pm
Здравствуйте. Сделал все как написано в статье но в итоге ничего не происходит. В чем может быть причина? Может ли быть причиной,что файл LocoTranslitFilter не подключается? 
#885
almix говорит:
May 30, 2013 at 02:11 am
Проверяйте какое поле транслитерируете. У меня оно называлось 'title'. У вас оно есть в таблице базы (модели)?
#887
red-ogurez говорит:
May 30, 2013 at 11:07 am
Спасибо. отличный экст.
#888
guest говорит:
May 30, 2013 at 05:32 pm

Да есть  поле title  и alias, вставляю строку  как то так 

public function rules()
{
   return array(
array('alias','ext.LocoTranslitFilter','translitAttribute'=>'title'),
array('title, alias', 'length', 'max'=>255),
// The following rule is used by search().
// Please remove those attributes that should not be searched.
array('id, title, alias', 'safe', 'on'=>'search'),
);
}

не работает .

#890
almix говорит:
May 31, 2013 at 12:52 am
А где в rules() - правило с required? Как вариант попробуйте путь прописать к фильтру полностью - application.extensions.LocoTranslitFilter