Symfony cyrillic routing slug



我有问题,路由参数。我想用"-"替换所有间隔和符号。当参数带有拉丁字母时,一切都有效,但是如果我尝试将参数与西里尔字母混合,我会出错。

路由:

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

例:我在 Databace 中有两个名字:

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

通常白廷函数网址是:

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

当我把函数结果是:

  • 英语
  • 在西里尔文版本上参数为空。

    空模块和/或解析 URL "/cat/1/" (/) 后的操作。

我建议你使用Doctrine::urlize而不是你自己的slugify函数(因为你使用的是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);
}

您也可以在整个项目中全局修复该行为。感谢symfony自动加载器,它在插件之前预先添加全局目录,你可以这样做:

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));
    }
}
测试/

单元/音译测试.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'
    )));

最新更新