1

slugify ルーティング パラメータに問題があります。すべての間隔と記号を「-」に置き換えたい。パラメータがラテン文字の場合はすべて機能しますが、パラメータをキリル文字でスラッグ化しようとするとエラーが発生します。

ルーティング:

 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;
}

例: データベースに 2 つの名前があります。

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

通常、Whitin 関数の URL は次のとおりです。

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

私が関数を入れたときの結果は次のとおりです。

  • 英語
  • キリル文字バージョンのパラメーターは空です。

    URL "/cat/1/" (/) を解析した後の空のモジュールおよび/またはアクション。

4

2 に答える 2

3

独自の slugify 関数の代わりにDoctrine::urlizeを使用することをお勧めします(Doctrine を使用しているため)。

次に、関数を次のように置き換えます。

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

編集:

実際、Doctrine は (2.0 でも) キリル文字をうまく扱えないようです。自分で処理する必要があります。私はこの機能を見つけました:

  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);
}
于 2012-06-04T14:57:27.637 に答える
2

プロジェクト全体でその動作をグローバルに修正することもできます。プラグインの前にグローバルディレクトリを追加する symfony autoloader のおかげで、次のようにすることができます:

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

lib/doctrine/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/doctrine/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 タスクで使用する場合は注意してください。実行環境のため、手動でプリロードする必要があります。sf1.4 cli タスクには独自の実行環境があり、私のプロジェクトでは Doctrine のオリジナルのクラスの前にこのクラスをプリロードしません。

//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'
    )));
于 2012-10-22T11:47:25.410 に答える