如何使用Doctrine和Gedmo可翻译扩展来获取不同翻译中的对象

时间:2015-01-19 14:53:23

标签: php symfony doctrine-orm doctrine translate

我遇到了以下问题:我想获取特定区域设置的doctrine实体,而不会破坏我的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()的实施中出了什么问题?

欢迎任何帮助或提示。

3 个答案:

答案 0 :(得分:0)

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

$em->refresh($product1);

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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

  1. 您的findOneProductInLocale(如果可以)。

    它像设计一样-当您使用findOneProductInLocale时,查询将在给定的语言环境中进行搜索,但最终实体将始终在当前语言环境中加载,则无法更改。

  2. 通过findOneProductInLocale找到实体,并加载到当前语言环境后,您可以使用{ {1}} Gedmo的方法并刷新实体,如@umadesign

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

    $local

您可以在Gedmo documentation under "Basic usage examples" subsection中找到完整的说明。