如何使用教义和 Gedmo 可翻译扩展获得不同翻译中的对象


How to get object in different translations with Doctrine and Gedmo Translatable Extension

我遇到了以下问题:我想在不破坏我的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()实现有问题吗?

欢迎任何帮助或提示。

我知道

我的答案有点晚了,但我面临同样的问题并找到了解决方案。我希望它能帮助其他一些开发人员。

  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 文档的"基本使用示例"小节下找到完整的说明。

刷新实体应恢复当前区域设置:

$em->refresh($product1);

问题是,你的$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');