Расширение Doctrine EntityManager с EntityManagerDecorator оставляет неправильную ссылку в UnitOfWork

Я пытаюсь продлить EntityManager в учении, используя EntityManagerDecorator и столкнулись с проблемой со ссылкой на базу EntityManager в UnitOfWork передается в prePersist событие через $eventArgs,

Похоже, EntityManager передается в UnitOfWork в EntityManager::__construct когда UnitOfWork создано.

Я думал, что решение может быть, что я могу переопределить по умолчанию UnitOfWork в MyEntityManagerDecorator::getUnitOfWork() лайк:

public function getUnitOfWork()
{
if ($this->unitOfWork === null) {
$this->unitOfWork = new UnitOfWork($this);
}

return $this->unitOfWork;
}

Однако я заметил, что UnitOfWork::__construct() требует EntityManager не EntityManagerInterface так что это не сработает.

Я ищу, как я могу получить MyEntityManagerDecorator от prePersist $eventArgs->getEntityManager() вместо базы EntityManager, Я хотел бы сделать это без прямого наследования EntityManager, Документы также говорят «Вы никогда не должны пытаться наследовать от EntityManager: Наследование не является допустимой точкой расширения для EntityManager»..

Я не уверен, что вам нужно для примеров кода, если таковые имеются, поэтому, пожалуйста, дайте мне знать, если вам требуется дополнительная информация. У меня есть доступ к MyEntityManagerDecorator как и ожидалось везде в проекте (что я пробовал до сих пор). Я устанавливаю декоратор в yml вот так:

my_multi_tenant_entity_manager:
public: false
class: My\MultiTenantBundle\ORM\MyEntityManagerDecorator
decorates: doctrine.orm.default_entity_manager
arguments: [ "@my_multi_tenant_entity_manager.inner" ]

Вот список пакетов и номеров версий, которые я использую, дамп из composer:

installed:
doctrine/annotations                 v1.2.3             Docblock Annotations Parser
doctrine/cache                       v1.4.0             Caching library offering...
doctrine/collections                 v1.2               Collections Abstraction ...
doctrine/common                      v2.4.2             Common Library for Doctr...
doctrine/dbal                        v2.5.1             Database Abstraction Layer
doctrine/doctrine-bundle             v1.3.0             Symfony DoctrineBundle
doctrine/doctrine-cache-bundle       v1.0.1             Symfony2 Bundle for Doct...
doctrine/doctrine-migrations-bundle  dev-master 6a1bd73 Symfony DoctrineMigratio...
doctrine/inflector                   v1.0.1             Common String Manipulati...
doctrine/instantiator                1.0.4              A small, lightweight uti...
doctrine/lexer                       v1.0.1             Base library for a lexer...
doctrine/migrations                  dev-master 058a463 Database Schema migratio...
doctrine/orm                         v2.4.7             Object-Relational-Mapper...
incenteev/composer-parameter-handler v2.1.0             Composer script handling...
jdorn/sql-formatter                  v1.2.17            a PHP SQL highlighting l...
kriswallsmith/assetic                v1.2.1             Asset Management for PHP
monolog/monolog                      1.12.0             Sends your logs to files...
phpdocumentor/reflection-docblock    2.0.4
phpspec/prophecy                     v1.3.1             Highly opinionated mocki...
phpunit/php-code-coverage            2.0.15             Library that provides co...
phpunit/php-file-iterator            1.3.4              FilterIterator implement...
phpunit/php-text-template            1.2.0              Simple template engine.
phpunit/php-timer                    1.0.5              Utility class for timing
phpunit/php-token-stream             1.4.0              Wrapper around PHP's tok...
phpunit/phpunit                      4.5.0              The PHP Unit Testing fra...
phpunit/phpunit-mock-objects         2.3.0              Mock Object library for ...
psr/log                              1.0.0              Common interface for log...
raven/raven                          dev-master 407d770 A PHP client for Sentry ...
sebastian/comparator                 1.1.1              Provides the functionali...
sebastian/diff                       1.2.0              Diff implementation
sebastian/environment                1.2.1              Provides functionality t...
sebastian/exporter                   1.2.0              Provides the functionali...
sebastian/global-state               1.0.0              Snapshotting of global s...
sebastian/recursion-context          1.0.0              Provides functionality t...
sebastian/version                    1.0.4              Library that helps with ...
sensio/distribution-bundle           v3.0.16            Base bundle for Symfony ...
sensio/framework-extra-bundle        v3.0.4             This bundle provides a w...
sensio/generator-bundle              v2.5.2             This bundle generates co...
sensiolabs/security-checker          v2.0.1             A security checker for y...
swiftmailer/swiftmailer              v5.3.1             Swiftmailer, free featur...
symfony/assetic-bundle               v2.6.1             Integrates Assetic into ...
symfony/monolog-bundle               v2.7.1             Symfony MonologBundle
symfony/swiftmailer-bundle           v2.3.8             Symfony SwiftmailerBundle
symfony/symfony                      v2.6.4             The Symfony PHP framework
twig/extensions                      v1.2.0             Common additional featur...
twig/twig                            v1.18.0            Twig, the flexible, fast...

2

Решение

Я бы предложил украсить (а не напрямую расширить) EntityManager, поскольку он теряет связь между вашей реализацией и унаследованным компонентом.

Чтобы иметь возможность отличать сущности, имеющие отношение к арендатору, внедряют / расширяют эти классы от interface или mapped superclass,

SecurityContext (для демонстрационных целей) предназначен для получения ссылки на арендатора.

/**
* `EntityManagerDecorator` exists since v2.4
*/
class MultiTenantEntityManager extends EntityManagerDecorator {

private $securityContext;

public function __construct(EntityManagerInterface $entityManager, $securityContext) {
parent::__construct($entityManager);
$this->securityContext = $securityContext;
}

public function persist($entity) {
// set the tenant before persisting an entity
if ($entity instanceof MultiTenantEntity) {
$userId = $this->securityContext->getUserId();
$tenant = $this->wrapped->find($userId,...);
$entity->setTenant($tenant);
}
return $this->wrapped->persist($entity);
}
}
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]