【问题标题】:How to implement a nice solution for multilang entity slug based routes in Symfony2如何在 Symfony2 中为基于多语言实体 slug 的路由实现一个很好的解决方案
【发布时间】:2015-01-28 17:32:30
【问题描述】:

我想创建一个简单的包来处理网站中的一些多语言页面,其中包含已翻译的 slug。

基于translatablesluggablei18nrouting

  1. 按照文档所述实现了一个实体(页面),其中包含标题、内容、slug 字段 + 语言环境属性
  2. 创建了一个新页面,设置其标题和内容,然后将其翻译为$page->setTranslatableLocale('de');,并再次使用德语值设置这些字段,以便表格中的数据看起来不错,它们都在那里
  3. 使用类型提示签名实现控制器:public function showAction(Page $page)
  4. 在模板中生成了一些 url:{{ path("page_show", {"slug": "test", "_locale": "en"}) }}{{ path("page_show", {"slug": "test-de", "_locale": "de"}) }},路由生成良好,看起来正确(/en/test 和 /de/test-de)
  5. 点击它们:

只有“en”翻译有效,“de”翻译失败:

未找到 MyBundle\Entity\Page 对象。

在检索页面时如何告诉 Symfony 或 Doctrine 或任何捆绑包使用当前语言环境?我是否必须创建一个 ParamConverter 然后将自定义 DQL 放入其中以手动完成工作? 谢谢!

【问题讨论】:

    标签: symfony routing translation slug


    【解决方案1】:

    刚刚找到了另一种我认为更好的解决方案,我将使用它!

    实现了一个存储库方法并在控制器的注释中使用它:

    @ParamConverter("page", class="MyBundle:Page", options={"repository_method" = "findTranslatedOneBy"})

    public function findTranslatedOneBy(array $criteria, array $orderBy = null)
    {
        $page = $this->findOneBy($criteria, $orderBy);
    
        if (!is_null($page)) {
            return $page;
        }
    
        $qb = $this->getEntityManager()
            ->getRepository('Gedmo\Translatable\Entity\Translation')
            ->createQueryBuilder('t');
    
        $i = 0;
        foreach ($criteria as $name => $value) {
            $qb->orWhere('t.field = :n'. $i .' AND t.content = :v'. $i);
            $qb->setParameter('n'. $i, $name);
            $qb->setParameter('v'. $i, $value);
            $i++;
        }
    
        /** @var \Gedmo\Translatable\Entity\Translation[] $trs */
        $trs = $qb->groupBy('t.locale', 't.foreignKey')->getQuery()->getResult();
    
        return count($trs) == count($criteria) ? $this->find($trs[0]->getForeignKey()) : null;
    }
    

    它的一个缺点是没有针对相同翻译值的保护...

    【讨论】:

      【解决方案2】:

      我找到了一个我不确定的解决方案,但它确实有效。

      实现了一个 PageParamConverter:

      class PageParamConverter extends DoctrineParamConverter
      {
      const PAGE_CLASS = 'MyBundle:Page';
      
      public function apply(Request $request, ParamConverter $configuration)
      {
          try {
              return parent::apply($request, $configuration);
          } catch (NotFoundHttpException $e) {
              $slug = $request->get('slug');
              $name = $configuration->getName();
              $class = $configuration->getClass();
              $em = $this->registry->getManagerForClass($class);
      
              /** @var \Gedmo\Translatable\Entity\Translation $tr */
              $tr = $em->getRepository('Gedmo\Translatable\Entity\Translation')
                  ->findOneBy(['content' => $slug, 'field' => 'slug']);
      
              if (is_null($tr)) {
                  throw new NotFoundHttpException(sprintf('%s object not found.', $class));
              }
      
              $page = $em->find($class, $tr->getForeignKey());
      
              $request->attributes->set($name, $page);
          }
      
          return true;
      }
      
      public function supports(ParamConverter $configuration)
      {
          $name = $configuration->getName();
          $class = $configuration->getClass();
      
          return parent::supports($configuration) && $class == self::PAGE_CLASS;
      }
      }
      

      【讨论】:

        【解决方案3】:

        TranslationWalker 很好地获取了活动语言环境中的实体:

        class PagesRepository extends \Doctrine\ORM\EntityRepository
        {
            public function findTranslatedBySlug(string $slug)
            {
                $queryBuilder = $this->createQueryBuilder("p");
        
                $queryBuilder
                    ->where("p.slug = :slug")
                    ->setParameter('slug', $slug)
                ;
        
                $query = $queryBuilder->getQuery();
        
                $query->setHint(
                    Query::HINT_CUSTOM_OUTPUT_WALKER,
                    'Gedmo\\Translatable\\Query\\TreeWalker\\TranslationWalker'
                );
        
                return $query->getSingleResult();
            }
        }
        

        在控制器中

         /**
         * @Entity("page", expr="repository.findTranslatedBySlug(slug)")
         * @param         $page
         *
         * @return Response
         */
        public function slug(Pages $page)
        {
        // thanks to @Entity annotation (Sensio\Bundle\FrameworkExtraBundle\Configuration\Entity) 
        // Pages entity is automatically retrieved by slug
        
            return $this->render('content/index.html.twig', [
                'page' => $page
            ]);
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-09-13
          • 1970-01-01
          • 2014-05-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多