【问题标题】:How to get object in different translations with Doctrine and Gedmo Translatable Extension如何使用 Doctrine 和 Gedmo 可翻译扩展获取不同翻译中的对象
【发布时间】:2015-03-17 14:52:03
【问题描述】:

我遇到了以下问题:我想在不破坏 Symfony 应用程序默认行为的情况下获取特定语言环境的学说实体。

这是我的一个实体的示例:

use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;

/**
 * @ORM\Entity(repositoryClass="ProductRepository")
 * @ORM\Table(name="product")
 * @ORM\InheritanceType("SINGLE_TABLE")
 * @ORM\DiscriminatorColumn(name="discr", type="string")
 */
class Product
{
    /**
     * @var integer $id
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @var string
     * @ORM\Column(name="name", type="string")
     * @Gedmo\Translatable
     */
    protected $name;

    // ...
}

相关学说库的一部分:

class ProductRepository extends \Doctrine\ORM\EntityRepository
{
    public function findOneProductInLocale($id, $locale)
    {
        $qb = $this->createQueryBuilder('p')
            ->select('p')
            ->where('p.id = :id')
            ->setMaxResults(1)
            ->setParameter('id', $id);
        ;

        $query = $qb->getQuery();

        $query->setHint(
            \Doctrine\ORM\Query::HINT_CUSTOM_OUTPUT_WALKER,
            'Gedmo\\Translatable\\Query\\TreeWalker\\TranslationWalker'
        );

        // force Gedmo Translatable to not use current locale
        $query->setHint(
            \Gedmo\Translatable\TranslatableListener::HINT_TRANSLATABLE_LOCALE,
            $locale
        );

        $query->setHint(
            \Gedmo\Translatable\TranslatableListener::HINT_FALLBACK,
            1
        );

        return $query->getOneOrNullResult();
    }
}

以及我的部分脚本:

// default Locale: en
// request Locale: de
$repo = $em->getRepository('Acme\\Entity\\Product');

$product1 = $repo->findOneById($id);
echo $product1->getName(); // return 'Name (DE)'

$product_de = $repo->findOneProductInLocale($id, 'de');
echo $product_de->getName(); // return 'Name (DE)';

$product_en = $repo->findOneProductInLocale($id, 'en');
echo $product_en->getName(); // return 'Name (EN)'

echo $product1->getName(); // return 'Name (EN)' instead of 'Name (DE)' !! <-- What is wrong?

// even if I refetch a product
$product2 = $repo->findOneById($id);
echo $product2->getName(); // return 'Name (EN)' without taking anymore in account the current locale

现在有人为什么这没有按预期工作? 我的ProductRepository::findOneProductInLocale() 的实现有问题吗?

欢迎任何帮助或提示。

【问题讨论】:

  • 因为您已经在 Product Repository 中设置了后备! $query-&gt;setHint( \Gedmo\Translatable\TranslatableListener::HINT_FALLBACK, 1 ); 这里 1 表示回退到默认语言环境

标签: php symfony doctrine-orm doctrine translate


【解决方案1】:

我知道我的回答有点晚了,但我遇到了同样的问题并找到了解决方案。希望对其他开发者有所帮助。

  1. 你的findOneProductInLocale 如果没问题的话。

    按设计工作 - 当您使用 findOneProductInLocale 时,查询将在给定的语言环境中搜索,但最终实体将始终被加载在当前语言环境中,您无法更改它。

  2. 一旦通过findOneProductInLocale 找到实体 & 在当前语言环境中加载,您可以使用 Gedmo 的 setTranslatableLocale 方法获得所需的语言环境变体并按照@umadesign 的说明刷新您的实体

    // Reload the entity in different languages.
    $entity->setTranslatableLocale($locale);
    $em->refresh($entity);
    
  3. (可选)您可能需要将setTranslatableLocale 方法和伴随属性$local 添加到您的可翻译实体中

    class Product {
      // ...
    
      /**
        * @Gedmo\Locale
        * Used locale to override Translation listener`s locale
        * this is not a mapped field of entity metadata, just a simple property
        */
      private $locale;
    
      /**
        * Set the locale to use for translation listener
        *
        * @param string $locale
        *
        * @return static
        */
      public function setTranslatableLocale($locale) {
          $this->locale = $locale;
          return $this;
      }
    
      // ...
    }
    

你可以在Gedmo documentation under "Basic usage examples" subsection找到完整的解释。

【讨论】:

    【解决方案2】:

    刷新实体应该恢复当前语言环境:

    $em->refresh($product1);
    

    【讨论】:

      【解决方案3】:

      问题是,你的$product1$product_de$product_en$product2 都是一样的。如果你var_dump 他们,他们有相同的object #id。他们指的是同一个Product Entity。如果你改变任何一个,它就会改变所有的。要使它们与众不同,您必须 clone 他们。

      $product_de = clone $repo->findOneProductInLocale($id, 'de');
      $product_en = clone $repo->findOneProductInLocale($id, 'en');
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-12
        • 1970-01-01
        • 1970-01-01
        • 2011-11-29
        • 2014-06-12
        • 1970-01-01
        相关资源
        最近更新 更多