Zend 2 Doctrine 2 Gedmo Translatable

2019-07-31 20:25发布

问题:

I am trying to use the Gedmo translatable extension for Doctrine 2 in a Zend Framework 2 application.

I have it setup like this:

'doctrine' => array(
    'eventmanager' => array(
        'orm_default' => array(
            'subscribers' => array(
                'Gedmo\Translatable\TranslatableListener'
            )
        )
    ),
    'driver' => array(
        'application_entities' => array(
            'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
            'cache' => 'array',
            'paths' => array(__DIR__ . '/../src/Application/Entity')
        ),
        'translatable_metadata_driver' => array(
            'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
            'cache' => 'array',
            'paths' => array(
                'vendor/gedmo/doctrine-extensions/lib/Gedmo/Translatable/Entity',
            )
        ),
        'orm_default' => array(
            'drivers' => array(
                'Application\Entity' => 'application_entities',
                'Gedmo\Translatable\Entity' => 'translatable_metadata_driver'
            )
        )
    ),
),

Sample Entity:

<?php

namespace Application\Entity;

use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * @ORM\Entity (repositoryClass="Application\Repository\CategoryRepository") 
 */
class Category {

    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

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

    /**
     * @Gedmo\Locale
     */
     private $locale;

}

Persisting translations works fine and I can get them using the translatable repository.

I have two problems:

  1. I cannot figure out how to get the translatable listener subscribed to the entitymanager. I would like to get it in the Module class to set the default locale on bootstrap.

  2. When I have an entity object I cannot get the translations of translatable columns, only the standard values. As far as I can figure out, I should get a value translated to the default locale, and should be able to override the default locale by setting a variable in the Entity annotated with Locale, but it does not seem to work.

Any help would be greatly appreciated!

回答1:

public function onBootstrap(MvcEvent $event)
{
    $serviceManager = $event->getApplication()->getServiceManager();

    $this->prepareGedmoTranslatable($serviceManager);
}

/**
 * Does initial config of Gedmo\TranslatableListener
 * sets default locale and registers it as service
 *
 * Reader you can ask why?
 * You will understand me if you try to use TranslatableListener yourself ;)
 *
 * @param ContainerInterface $services
 */
public function prepareGedmoTranslatable(ContainerInterface $services)
{
    /**
     * @var EventManager $ormEventManager
     */
    $ormEventManager      = $services->get('doctrine.eventmanager.orm_default');
    // assume that postLoad event has TranslatableListener as listener
    // it will be if TranslatableListener enabled in doctrine config
    // Doctrine\ORM\Events::postLoad
    $listeners            = $ormEventManager->getListeners(Events::postLoad);
    $translatableListener = null;

    // search for TranslatableListener cause Gedmo loves hardcore stuff ;)
    foreach ($listeners as $listener) {
        if ($listener instanceof TranslatableListener) {
            $translatableListener = $listener;
            break;
        }
    }

    if ($translatableListener instanceof TranslatableListener) {
        $translatableListener->setDefaultLocale(
            // assume that translator config provides default locale
            // e.g locale that have been set in config
            $services->get('config')['translator']['locale']
        );

        // let translations to fallback to default locale
        $translatableListener->getTranslationFallback(true);

        // lines below adds Listener as a service so you can access it by
        // $services->get(TranslatableListener::class)
        // everywhere you want
        $services->setAllowOverride(true);
        $services->setService(TranslatableListener::class, $translatableListener);
        $services->setAllowOverride(false);
    }
}

Glad to help you!