2012-06-04 59 views
1

我有問題whit slugify路由參數。我想用「 - 」替換所有間隔和符號。當參數與拉丁字母都工作,但如果我嘗試slugify參數惠氏西裏爾字母我得到錯誤。Symfony西里爾路由段塞

路由:

catTests: 
     url: /cat/:id/:name_slug 
     class: sfDoctrineRoute 
     options: { model: categories, type: object } 
     param: { module: categories, action: testsByCat } 
     requirements: 
     id: \d+ 

蛞蝓功能:

static public function slugify($text) 
{ 
    // replace all non letters or digits by - 
    $text = preg_replace('/\W+/', '-', $text); 

    // trim and lowercase 
    $text = strtolower(trim($text, '-')); 

    return $text; 
} 

public function getNameSlug() 
{ 
    $text= Category::slugify($this->getName()); 
    return $text; 
} 

實施例: i的databace有兩個名字:

  • 英語
  • Български語

通常whitin功能的網址是:

  • 英語+語言
  • Български+език

當我把函數的結果是:

  • 英語
  • 和西里爾文ve rsion參數爲空。

    解析URL「/ cat/1 /」(/)後爲空模塊和/或動作。

回答

3

我建議你使用Doctrine::urlize,而不是你自己的slugify功能(因爲你正在使用原則)。

,然後更換您喜歡的功能:

public function getNameSlug() 
{ 
    return Doctrine_Inflector::urlize($this->getName()); 
} 

編輯:

事實上,似乎學說不能很好地處理西里爾(甚至在2.0)。你將不得不自己處理它。我發現this function

public static function replaceCyrillic ($text) 
    { 
    $chars = array(
     'ґ'=>'g','ё'=>'e','є'=>'e','ї'=>'i','і'=>'i', 
     'а'=>'a', 'б'=>'b', 'в'=>'v', 
     'г'=>'g', 'д'=>'d', 'е'=>'e', 'ё'=>'e', 
     'ж'=>'zh', 'з'=>'z', 'и'=>'i', 'й'=>'i', 
     'к'=>'k', 'л'=>'l', 'м'=>'m', 'н'=>'n', 
     'о'=>'o', 'п'=>'p', 'р'=>'r', 'с'=>'s', 
     'т'=>'t', 'у'=>'u', 'ф'=>'f', 'х'=>'h', 
     'ц'=>'c', 'ч'=>'ch', 'ш'=>'sh', 'щ'=>'sch', 
     'ы'=>'y', 'э'=>'e', 'ю'=>'u', 'я'=>'ya', 'é'=>'e', '&'=>'and', 
     'ь'=>'', 'ъ' => '', 
    ); 

    return strtr($text, $chars); 
    } 

然後:

public function getNameSlug() 
{ 
    $slug = Category::replaceCyrillic($this->getName()); 
    return Doctrine_Inflector::urlize($slug); 
} 
+0

ok我試過了,但結果是一樣的。函數只對我的Db中的拉丁名稱起作用:( – plamen

+0

)你能發佈(在你的問題中)錯誤和西里爾字符的問題嗎? – j0k

+0

是的!這個函數是工作的,但是由於教條不支持cirillic。我嘖嘖網址惠普+是更好的拉丁。 – plamen

2

您可以修復行爲globaly各地的項目太多。 感謝symfony的自動加載該插件的你能做到這樣之前預先考慮您的全局目錄:

mkdir lib/doctrine 
touch lib/doctrine/Inflector_Cyrilic.php 
touch lib/doctrine/Sluggable.php 
touch test/unit/TransliterationTest.php 

的lib /教義/ Inflector_Cyrilic.php:

<?php 
class Doctrine_Inflector_Cyrilic extends Doctrine_Inflector 
{ 

    /** 
    * @param string $text 
    * @param Doctrine_Record $record 
    * 
    * @return string 
    */ 
    public static function urlizeExtended($text, $record) { 
     // we need to use other method name because of PHP strict standards (one more attribute unlike parent so its not compatible) 
     // $record attribute is given here standardly, it was only not used before 

     //XXX this sollution expect youll have all slugs in Translation records (in I18n in schema.yml) 
     // You can alter this conditions how do you need for your project 
     // this is important because this should not be used on other writing systems 

     if (preg_match('/Translation$/', get_class($record))) { 
      if ($record->lang === 'ru') { 
       $text = self::cyrilicToLatin($text); 
      } 
     } 
     return parent::urlize($text); 
    } 

    /** 
    * @param string $text 
    * 
    * @return string 
    */ 
    public static function cyrilicToLatin ($text) 
    { 
     $chars = array(
      'ґ'=>'g','ё'=>'e','є'=>'e','ї'=>'i','і'=>'i', 
      'а'=>'a', 'б'=>'b', 'в'=>'v', 
      'г'=>'g', 'д'=>'d', 'е'=>'e', 'ё'=>'e', 
      'ж'=>'zh', 'з'=>'z', 'и'=>'i', 'й'=>'i', 
      'к'=>'k', 'л'=>'l', 'м'=>'m', 'н'=>'n', 
      'о'=>'o', 'п'=>'p', 'р'=>'r', 'с'=>'s', 
      'т'=>'t', 'у'=>'u', 'ф'=>'f', 'х'=>'h', 
      'ц'=>'c', 'ч'=>'ch', 'ш'=>'sh', 'щ'=>'sch', 
      'ы'=>'y', 'э'=>'e', 'ю'=>'u', 'я'=>'ya', 'é'=>'e', 
      'ь'=>'', 'ъ' => '', 
     ); 
     return strtr($text, $chars); 
    } 

} 

的lib /教義/ Sluggable 。PHP:

<?php 
/** 
* we cannot use inheritance here because we are replacing class by otherone with the same name 
*/ 
class Doctrine_Template_Sluggable extends Doctrine_Template 
{ 

    /** 
    * Array of Sluggable options 
    * 
    * @var string 
    */ 
    protected $_options = array(
     'name'   => 'slug', 
     'alias'   => NULL, 
     'type'   => 'string', 
     'length'  => 255, 
     'unique'  => TRUE, 
     'options'  => array(), 
     'fields'  => array(), 
     'uniqueBy'  => array(), 
     'uniqueIndex' => TRUE, 
     'canUpdate'  => FALSE, 
     'builder'  => array('Doctrine_Inflector_Cyrilic', 'urlizeExtended'), 
     'provider'  => NULL, 
     'indexName'  => NULL 
    ); 

    /** 
    * Set table definition for Sluggable behavior 
    * 
    * @return void 
    */ 
    public function setTableDefinition() 
    { 
     $name = $this->_options['name']; 
     if ($this->_options['alias']) { 
      $name .= ' as ' . $this->_options['alias']; 
     } 
     if ($this->_options['indexName'] === NULL) { 
      $this->_options['indexName'] = $this->getTable()->getTableName().'_sluggable'; 
     } 
     $this->hasColumn($name, $this->_options['type'], $this->_options['length'], $this->_options['options']); 

     if ($this->_options['unique'] == TRUE && $this->_options['uniqueIndex'] == TRUE) { 
      $indexFields = array($this->_options['name']); 
      $indexFields = array_merge($indexFields, $this->_options['uniqueBy']); 
      $this->index($this->_options['indexName'], array('fields' => $indexFields, 
        'type' => 'unique')); 
     } 

     $this->addListener(new Doctrine_Template_Listener_Sluggable($this->_options)); 
    } 

} 

測試/單位/ TransliterationTest.php:

<?php 

// some bootstrapping of your tests 

$record = Doctrine_Core::getTable('YourTable')->create(array(
     'record params....' 
    )); 
$record->Translation['ru']->name = 'холодильник'; 
$record->save(); 
$t->ok(preg_match('/^holodilnik/', $record->Translation['ru']->slug), '  RU slug transliterated cyrilic to latin'); 

如果你想在CLI任務使用它小心,你必須預先加載它manualy那裏,因爲它的運行環境。 sf1.4 cli任務有它自己特定的運行環境,並且在我的項目中,它不會在原始教程前預加載這個類。

//i have this in my abstract class which is parent of each my cli tasks 
require_once(implode(DIRECTORY_SEPARATOR, array(
     __DIR__, '..', 
     'Doctrine', 
     'Sluggable.php' 
    )));