【问题标题】:Custom i18n routing in SymfonySymfony 中的自定义 i18n 路由
【发布时间】:2013-06-12 07:32:30
【问题描述】:

我正在使用JMS\I18nRoutingBundleGedmo\TranslatableGedmo\Sluggable。具有默认位置的路由也可以工作,但其他语言环境无需翻译 slug 即可工作。我的 i18n 路由有以下设置:

# Doctrine extensions
stof_doctrine_extensions:
    default_locale: %locale%
    translation_fallback: true
    orm:
        default:
            #…
            sluggable:      true
            translatable:   true
            loggable:       false
            #…

jms_i18n_routing:
    default_locale: cs_CZ
    locales: [cs_CZ, en_US]
    strategy: custom
    hosts:
        cs_CZ: example.cz
        en_US: example.com
    redirect_to_host: true

当我这样设置路线时:

hw_category:
    pattern: /category/{slug}
    defaults: { _controller: AcmeSiteBundle:Category:detail }
/**
 * @Template
 */
public function detailAction(Category $category)
{}

这条路线有效
example.cz/category/slug-in-czech
example.com/category/slug-in-czech

但我想工作 example.com/category/slug-in-english 会引发 404 异常 object not found

【问题讨论】:

    标签: symfony internationalization routing


    【解决方案1】:

    在您的控制器中,您必须覆盖实体存储库中使用的方法:

    /**
     * @Template
     * @ParamConverter(
     *     "category",
     *     class = "AcmeSiteBundle:Category",
     *     options = {
     *         "repository_method" = "findByTranslatedSlug"
     *     }
     *  )
     */
    public function detailAction(Category $category)
    {}
    

     

    namespace Acme\Bundle\SiteBundle\Entity;
    
    use Doctrine\ORM\EntityRepository;
    
    class CategoryRepository extends EntityRepository
    {
        public function findByTranslatedSlug($slug)
        {
            $qb = $this->createQueryBuilder('c')
                ->where('c.slug = :slug')
                ->setParameters($slug);
    
            $query = $qb->getQuery();
            // set the translation query hint
            $query->setHint(
                \Doctrine\ORM\Query::HINT_CUSTOM_OUTPUT_WALKER,
                'Gedmo\\Translatable\\Query\\TreeWalker\\TranslationWalker'
            );
    
            return $query->getOneOrNullResult();
        }
    }
    

    【讨论】:

      【解决方案2】:

      我看到您正在使用 ParamConverter 自动获取您的类别。

      如果 slug-in-english 是您数据库中的现有 slug,但教义拒绝获取它。

      此时您可能没有将 TranslatableListener 添加到您的 EntityManager 中。

      示例

      $translatableListener = new \Gedmo\Translatable\TranslationListener();
      $translatableListener->setTranslatableLocale('en_us');
      $em->addEventSubscriber($translatableListener);
      

      如果您使用的是 StofDoctrineExtensionsBundle

      stof_doctrine_extensions:
          default_locale: en_US
          orm:
              default:
                  # ...
                  translatable: true
      

      【讨论】:

      • 我应该在哪里附加TranslatableListener - 在哪个文件中?
      • 你在使用 StofDoctrineExtensionsBundle 吗?
      • 是的,我使用 StofDoctrineExtensionBundle 并且我之前已经配置过了。 (我想你的意思是translatable - 不是timestampable。)扩展顺序重要吗?
      【解决方案3】:

      我遇到了同样的问题,按照 jkucharovic 的建议,您可以使用 Doctrine ParamConverter 将您的请求参数转换为对象

      为了从数据库中获取对象,Doctrine 转换器默认使用 find() 方法。但是由于我们使用Translatable,因此使用多个表,仅管理翻译是不够的,这就是我们需要定义自己的原因。 findByTranslatedSlug 来了。

      /**
       * @Template
       * @ParamConverter(
       *     "category",
       *     class = "AcmeSiteBundle:Category",
       *     options = {
       *         "id" = "slug",
       *         "repository_method" = "findByTranslatedSlug"
       *     }
       *  )
       */
      public function detailAction(Category $category)
      {}
      

      ParamConverter参数的一些细节:

      • 第一个参数“category”指的是方法参数的名称(这里是$category
      • “id” 选项是指您要传递的路由占位符(此处为 {slug})到自定义存储库方法(findByTranslatedSlug())。如果不设置此选项,则会引发 PDO 异常。

       

      namespace Acme\Bundle\SiteBundle\Entity;
      
      use Doctrine\ORM\EntityRepository;
      
      class CategoryRepository extends EntityRepository
      {
          public function findByTranslatedSlug($slug)
          {
              $qb = $this->createQueryBuilder('c')
                  ->where('c.slug = :slug')
                  ->setParameter('slug',$slug);
      
              $query = $qb->getQuery();
              // set the translation query hint
              $query->setHint(
                  \Doctrine\ORM\Query::HINT_CUSTOM_OUTPUT_WALKER,
                  'Gedmo\\Translatable\\Query\\TreeWalker\\TranslationWalker'
              );
              // If you need to set manually the locale to en_US, you can set this query hint
              //$query->setHint(\Gedmo\Translatable\TranslatableListener::HINT_TRANSLATABLE_LOCALE, 'en_US');
      
              return $query->getOneOrNullResult();
          }
      }
      

      希望对你有帮助

      文档:

      【讨论】:

        【解决方案4】:

        对于 Symfony > 4 解决方法是

        use Sensio\Bundle\FrameworkExtraBundle\Configuration\Entity;
        
             * @Route("/{slug}", name="your_route_name"))
             * @Entity("your_entity_name", expr="repository.findByTranslatedSlug(slug)")
        

        并使用已接受答案中的 repo 方法;)

        一整天都在搜索这个,我很高兴找到你的帖子!

        【讨论】:

          猜你喜欢
          • 2016-05-17
          • 1970-01-01
          • 2018-02-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-02-10
          相关资源
          最近更新 更多