Y a-t-il un moyen de spécifier la classe D'implémentation Doctrine2 Entitymanager dans Symfony2?

je travaille actuellement avec Symfony2 et Doctrine2, mais je dois outrepasser la Doctrine2 EntityManager et l'ajouter quelques fonctionnalités" undelete " (ACLs à l'intérieur).

alors je me demande : y a-t-il un moyen d'outrepasser la classe EntityManager et de spécifier Doctrine2 dans Symfony2 pour l'utiliser comme implémentation de L'EntityManager?

Merci pour toute aide!

5
demandé sur Yoann Chambonnet 2011-11-15 19:41:37

4 réponses

Oui, c'est possible avec deux étapes:

1-Outrepasser le paramètre doctrine.orm.entity_manager.class pour pointer vers votre gestionnaire d'entité personnalisé (qui devrait étendre Doctrine\ORM\EntityManager ).)

2-Votre gestionnaire d'entité personnalisé doit outrepasser la méthode create pour qu'il renvoie une instance de votre classe. Voir mon exemple ci-dessous, et noter la dernière ligne concernant MyEntityManager :

public static function create($conn, Configuration $config, EventManager $eventManager = null) {
        if (!$config->getMetadataDriverImpl()) {
            throw ORMException::missingMappingDriverImpl();
        }

        if (is_array($conn)) {
            $conn = \Doctrine\DBAL\DriverManager::getConnection($conn, $config, ($eventManager ? : new EventManager()));
        } else if ($conn instanceof Connection) {
            if ($eventManager !== null && $conn->getEventManager() !== $eventManager) {
                throw ORMException::mismatchedEventManager();
            }
        } else {
            throw new \InvalidArgumentException("Invalid argument: " . $conn);
        }

        // This is where you return an instance of your custom class!
        return new MyEntityManager($conn, $config, $conn->getEventManager());
    }

vous aurez également besoin de use les suivants en votre classe:

use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Configuration;
use Doctrine\ORM\ORMException;
use Doctrine\Common\EventManager;
use Doctrine\DBAL\Connection;

pour être honnête, je suis surpris que la deuxième étape est nécessaire à tous, je pense que cela devrait être possible d'accomplir en utilisant seulement le conteneur de service.

6
répondu Steven Mercatante 2011-11-15 16:52:16

après Doctrine 2.4 ( Doctrine 2.4 release ) vous devez utiliser décorateur pour cela. Ne pas étendre EntityManager directement. Tout d'abord, vous devez mettre en œuvre votre propre décorateur de gestionnaire d'entité qui étend la Doctrine\ORM\Decorator\EntityManagerDecorator (comme @Dana) Mais vous ne pouvez pas changer la doctrine.orm.entity_manager.classe à votre nouveau décorateur parce que EntityManagerDecorator nécessite EntityManagerInterface dans son constructeur:

public function __construct(EntityManagerInterface $wrapped)

Vous ne pouvez pas passer la doctrine.orm.entity_manager comme paramètre ici parce que ce sera une récursion. Et ne faites pas comme ceci:

return new self(\Doctrine\ORM\EntityManager::create(

ce dont vous avez besoin est de configurer votre décorateur dans les services comme un décorateur:

yourcompany_entity_manager:
    public: false
    class: YourCompany\ORM\EntityManagerDecorator
    decorates: doctrine.orm.default_entity_manager
    arguments: ["@yourcompany_entity_manager.inner"]

Maintenant vous aurez votre décorateur comme un directeur d'entité par défaut pour la Doctrine. @yourcompany_entity_manager.inner est en fait un lien avec la doctrine .orm.default_entity_manager qui sera passé à votre entrepreneur_entity_manager constructeur.

Symfony-docs pour la configuration des décorateurs: lien

Btw cette commande est très utile pour déboguer vos services:

app/console container: debug | grep entity_manager

20
répondu user2563451 2014-11-27 13:10:17

au moins dans la Doctrine / ORM 2.4, la chaîne doc de la classe EntityManager décourage explicitement d'hériter de la Doctrine\ORM\EntityManager, au lieu de cela ils suggèrent d'hériter de la Doctrine\ORM\Decorator\EntityManagerDecorator:

/**
 * The EntityManager is the central access point to ORM functionality.
 * ...
 * You should never attempt to inherit from the EntityManager: Inheritance
 * is not a valid extension point for the EntityManager. Instead you
 * should take a look at the {@see \Doctrine\ORM\Decorator\EntityManagerDecorator}
 * and wrap your entity manager in a decorator.
 * ...
 */
/* final */class EntityManager implements EntityManagerInterface
{
    ...

donc, étendez EntityManagerDecorator et faites les changements dont vous avez besoin. Vous aurez besoin d'implémenter la méthode create() factory, mais vous n'avez pas besoin de copier L'implémentation D'EntityManager maintenant:

use Doctrine\ORM\Decorator\EntityManagerDecorator;
use Doctrine\Common\EventManager;
use Doctrine\ORM\Configuration;

class MyEntityManager extends EntityManagerDecorator
{
    /**
     * {@inheritDoc}
     */
    public function persist($entity)
    {
        // do something interesting
        parent::persist($entity);
    }

    public function create($conn, Configuration $config, EventManager $eventManager = null)
    {
        return new self(\Doctrine\ORM\EntityManager::create($conn, $config, $eventManager));
    }
}

alors annulez la doctrine.orm.entity_manager.paramètre classe de point personnalisé entité gestionnaire de classe.

les docs ne couvrent pas tout, dans de nombreux cas, il suffit de lire le code.

3
répondu Dana 2014-05-29 14:21:40

j'ai trouvé le processus de étendre le gestionnaire d'entité extrêmement contre-intuitif, malgré une bonne compréhension des concepts tels que l'injection de dépendances, le Localisateur de service, la génération de code, la mise en cache et le motif décorateur.

J'espère que cet exemple concis vous donnera une image claire (ceci développe la réponse de @user2563451)

version Symfony (Lun Aug 20 13: 05:58 CEST 2018)

$ composer info | grep -E -e symfony/framework  -e 'doctrine/(common|orm|dbal)'
doctrine/common             v2.9.0             Common Library for Doctrine projects
doctrine/dbal               v2.8.0             Database Abstraction Layer
doctrine/orm                v2.6.2             Object-Relational-Mapper for PHP
symfony/framework-bundle    v4.1.3             Symfony FrameworkBundle

config / services.yaml

App\Doctrine\ORM\CustomEntityManager:
    public: false # optional afaik
    decorates: doctrine.orm.original_entity_manager
    arguments: [ '@App\Doctrine\ORM\CustomEntityManager.inner' ]

config/packages / doctrine.yaml

doctrine:
    orm:
        auto_generate_proxy_classes: '%kernel.debug%'
        default_entity_manager: original
        entity_managers:
            original:
                connection: from_env
                naming_strategy: doctrine.orm.naming_strategy.underscore
                auto_mapping: false
                mappings:
                    TimeTracking:
                        is_bundle: false
                        type: annotation
                        dir: '%kernel.project_dir%/src/php/Model'
                        prefix: TimeTracking\Model
                        alias: TimeTracking
                        mapping: true
            #mapper_number_5:
            #    (...)

src/php/App/Doctrine/ORM / CustomEntityManager.php

<?php

namespace App\Doctrine\ORM;

use App\Doctrine\ORM\Proxy\SoggyProxyFactory;
use Doctrine\ORM\Decorator\EntityManagerDecorator;
use Doctrine\ORM\Proxy\ProxyFactory;

/**
 * Writes custom proxy-class methods with support for the set-or-get-trait
 * @property  ProxyFactory soggyProxyFactory
 */
class CustomEntityManager extends EntityManagerDecorator
{
    /// SUPER: __construct(EntityManagerInterface $wrapped) { $this->wrapped = $wrapped; }
    private $soggyProxyFactory;
    public function getProxyFactory() {
        $config = $this->getConfiguration();
        if (null === $this->soggyProxyFactory) {
            $this->soggyProxyFactory = new SoggyProxyFactory(
                $this,
                $config->getProxyDir(),
                $config->getProxyNamespace(),
                $config->getAutoGenerateProxyClasses()
            );
        }
        return $this->soggyProxyFactory;
    }
}

références

http://symfony.com/doc/current/service_container/service_decoration.html

https://symfony.com/doc/current/doctrine/multiple_entity_managers.html

0
répondu Ярослав Рахматуллин 2018-08-20 11:08:03