Есть ли способ указать класс реализации Doctrine2 Entitymanager в Symfony2? - PullRequest
6 голосов
/ 15 ноября 2011

В настоящее время я работаю с Symfony2 и Doctrine2, но я должен переопределить Doctrine2 EntityManager и добавить в него некоторые функции «удаления» (ACL внутри).переопределить класс EntityManager и указать Doctrine2 в Symfony2, чтобы использовать его в качестве реализации EntityManager?

Спасибо за любую помощь!

Ответы [ 4 ]

20 голосов
/ 27 ноября 2014

После Doctrine 2.4 ( Doctrine 2.4 release ) вам нужно использовать для этого декоратор. Не расширяйте EntityManager напрямую. Для начала вам нужно реализовать собственный декоратор менеджера сущностей, который расширяет Doctrine \ ORM \ Decorator \ EntityManagerDecorator (например, @Dana). Но вы не можете просто изменить doctrine.orm.entity_manager.class на новый декоратор, потому что EntityManagerDecorator требует EntityManagerInterface в своем конструкторе:

public function __construct(EntityManagerInterface $wrapped)

Вы не можете просто передать doctrine.orm.entity_manager в качестве параметра здесь, потому что это будет рекурсия. И не делай так:

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

Вам нужно настроить декоратор в таких сервисах, как декоратор:

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

Теперь у вас будет ваш декоратор в качестве менеджера сущностей по умолчанию для Doctrine. @yourcompany_entity_manager.inner фактически является ссылкой на doctrine.orm.default_entity_manager , которая будет передана yourcompany_entity_manager конструктору.

Документы Symfony для настройки декораторов: ссылка

Кстати, эта команда очень полезна для отладки ваших сервисов:

контейнер приложения / консоли: отладка | grep entity_manager

7 голосов
/ 15 ноября 2011

Да, это возможно в два этапа:

1 - переопределить параметр doctrine.orm.entity_manager.class, чтобы он указывал на пользовательский менеджер сущностей (который должен расширяться Doctrine\ORM\EntityManager.)

2 - Ваш пользовательский менеджер сущностей должен переопределить метод create, чтобы он возвращал экземпляр вашего класса. Смотрите мой пример ниже и обратите внимание на последнюю строку, касающуюся 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());
    }

Вам также понадобится use следующее в вашем классе:

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

Если честно, я удивлен, что 2-й шаг вообще необходим, я думаю, что это возможно сделать, используя только сервисный контейнер.

3 голосов
/ 29 мая 2014

По крайней мере, в Doctrine / ORM 2.4 строка документа класса EntityManager явно не рекомендует наследовать от Doctrine \ ORM \ EntityManager, вместо этого они предлагают наследовать от 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
{
    ...

Итак, расширьте EntityManagerDecorator и внесите все необходимые изменения. Вам нужно будет реализовать фабричный метод create (), но вам не нужно сейчас копировать реализацию EntityManager:

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));
    }
}

Затем переопределите параметр doctrine.orm.entity_manager.class, чтобы он указывал на ваш пользовательский класс менеджера сущностей.

Документы не охватывают все, во многих случаях вам просто нужно прочитать код.

0 голосов
/ 20 августа 2018

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

Надеюсь, этот краткий пример прояснит для вас ясную картину (подробности ответа @ user2563451)

Версия Symfony (понедельник, 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

конфиг / services.yaml

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

конфиг / пакеты / 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 / приложение / Учение / ОРМ / 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;
    }
}

ссылки

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...