我想创建一个简单的包来处理带有翻译slugs的网站中的一些多语言页面。
基于translatable,sluggable和i18nrouting
$page->setTranslatableLocale('de');
并再次使用德语值设置这些字段,以便表格中的数据看起来很好,它们都在那里public function showAction(Page $page)
{{ path("page_show", {"slug": "test", "_locale": "en"}) }}
和{{ path("page_show", {"slug": "test-de", "_locale": "de"}) }}
,路由生成正常,看起来正确(/ en / test和/ de / test-de)只有“en”翻译有效,“de”翻译失败:
找不到MyBundle \ Entity \ Page对象。
如何在检索页面时告诉Symfony或Doctrine或其他任何包使用当前语言环境?我是否必须创建ParamConverter然后将自定义DQL手动放入其中? 谢谢!
答案 0 :(得分: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;
}
它有一个缺点,就是没有针对相同翻译价值的保护......
答案 1 :(得分:0)
我找到了一个解决方案,我不确定最好,但有效。
实施了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;
}
}
答案 2 :(得分:0)
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
]);
}