Обработка переводимых сущностей с переводом, хранящимся в той же строке, с помощью Doctrine

Я ищу решение для автоматического перевода объектов моего приложения Symfony. Я застрял в устаревшей базе данных, где переводы хранятся в той же таблице, что и дополнительные поля:

id | name | name_de | name_fr
 1 | cat  | Katze   | chat
 2 | dog  | Hund    | chien

Моя сущность отображается соответственно:

class Animal
{
    /**
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     *
     * @var integer
     */
    private $id;

    /**
     * @ORM\Column(name="name", type="string", length=64, nullable=false)
     *
     * @var string
     */
    private $name;

    /**
     * @ORM\Column(name="name_de", type="string", length=64, nullable=false)
     *
     * @var string
     */
    private $nameDe;

    /**
     * @ORM\Column(name="name_fr", type="string", length=64, nullable=false)
     *
     * @var string
     */
    private $nameFr;

    /* Followed by getters and setters */
}

Я уже рассматривал расширение Translatable, но оно не может соответствует моей схеме базы данных. Я также начал с пользовательской аннотации, подключающейся к событию postLoad, но затем меня остановила простая проблема, заключающаяся в том, что postLoad может запускаться в прокси-состоянии сущности.

Затем я бы посмотрел на пользовательский обходчик запросов (в основном модифицированный подход расширения Translatable), но я надеюсь, что там есть менее сложное решение.

Ура Матиас


person althaus    schedule 10.12.2015    source источник


Ответы (1)


Здесь довольно много решений, и я думаю, что я не просмотрел половину из них.

Во всяком случае, наименее сложное и, по крайней мере, немного чистое решение, которое я придумал до сих пор, — это использование статического класса для перевода. Это может выглядеть примерно так:

class Translation
{

    /**
     * @var string
     */
    private static $language;

    /**
     * tries to get a translated property by prepending the
     * configured language to the given entities getter
     *
     * @param object $entity
     * @param string $getter
     * @return mixed
     */
    public static function getTranslated($entity, $getter) {
        $language = self::getLanguage();
        $translatedGetter = $getter.$language;
        if(method_exists($entity, $translatedGetter)) {
            return $entity->$translatedGetter();
        } else {
            return $entity->$getter;
        }
    }

    /**
     * @return string
     */
    public static function getLanguage()
    {
        return self::$language;
    }

    /**
     * @param string $language
     */
    public static function setLanguage($language)
    {
        self::$language = ucfirst(strtolower($language));
    }

}

Затем вы устанавливаете язык всякий раз, когда ваше приложение запускается, и реализуете переводы либо в своих объектах:

/**
 * @return string
 */
public function getName()
{
    return Translation::getTranslated($this, __FUNCTION__);
}

или вызовите его извне:

Translation::getTranslated($animal, "getName");

Итак, с первым методом этот код:

Translation::setLanguage("DE");

// far more code

/** @var Animal[] $animals */
$animals = $entityManager->getRepository(Animal::class)->findAll();

foreach ($animals as $animal) {
    echo $animal->getName()."<br >";
}

выложил бы:

Katze
Hund

Конечно, это всего лишь один из способов сделать это со статическим классом.

person StoryTeller    schedule 10.12.2015