-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added PersisterFactory to ORM. #1260
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,6 +19,7 @@ | |
|
||
namespace Doctrine\ORM; | ||
|
||
use Doctrine\ORM\Persisters\PersisterFactory; | ||
use Exception; | ||
use Doctrine\Common\EventManager; | ||
use Doctrine\DBAL\Connection; | ||
|
@@ -82,6 +83,13 @@ | |
*/ | ||
private $metadataFactory; | ||
|
||
/** | ||
* The persister factory, used to retrieve the ORM persister of collections and entity classes. | ||
* | ||
* @var \Doctrine\ORM\Persisters\PersisterFactory | ||
*/ | ||
private $persisterFactory; | ||
|
||
/** | ||
* The UnitOfWork used to coordinate object-level transactions. | ||
* | ||
|
@@ -156,6 +164,7 @@ protected function __construct(Connection $conn, Configuration $config, EventMan | |
$this->metadataFactory->setEntityManager($this); | ||
$this->metadataFactory->setCacheDriver($this->config->getMetadataCacheImpl()); | ||
|
||
$this->persisterFactory = new PersisterFactory($this); | ||
$this->repositoryFactory = $config->getRepositoryFactory(); | ||
$this->unitOfWork = new UnitOfWork($this); | ||
$this->proxyFactory = new ProxyFactory( | ||
|
@@ -190,6 +199,16 @@ public function getMetadataFactory() | |
return $this->metadataFactory; | ||
} | ||
|
||
/** | ||
* Gets the persister factory used to manipulate collection and entity classes. | ||
* | ||
* @return \Doctrine\ORM\Persisters\PersisterFactory | ||
*/ | ||
public function getPersisterFactory() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This method doesn't seem to fit the EntityManager at all: it would honestly be better to not expose it to end-users like this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree that it seems the wrong way to expose it There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hibernate exposes it at EntityManager level because it can be swappable with another implementation. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TL;DR: the UnitOfWork as-is is already poop: let's stash poop in there instead of shoveling it on other classes. That makes our EntityManager some kind of locator (meh). The UnitOfWork as we know it will go away at some point in time, while the EntityManager will stay and be consumed by userland. |
||
{ | ||
return $this->persisterFactory; | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
|
@@ -411,6 +430,7 @@ public function find($entityName, $id, $lockMode = null, $lockVersion = null) | |
throw ORMException::unrecognizedIdentifierFields($class->name, array_keys($id)); | ||
} | ||
|
||
$persister = $this->persisterFactory->getOrCreateEntityPersister($class->name); | ||
$unitOfWork = $this->getUnitOfWork(); | ||
|
||
// Check identity map first | ||
|
@@ -427,16 +447,13 @@ public function find($entityName, $id, $lockMode = null, $lockVersion = null) | |
case LockMode::NONE === $lockMode: | ||
case LockMode::PESSIMISTIC_READ === $lockMode: | ||
case LockMode::PESSIMISTIC_WRITE === $lockMode: | ||
$persister = $unitOfWork->getEntityPersister($class->name); | ||
$persister->refresh($sortedId, $entity, $lockMode); | ||
break; | ||
} | ||
|
||
return $entity; // Hit! | ||
} | ||
|
||
$persister = $unitOfWork->getEntityPersister($class->name); | ||
|
||
switch (true) { | ||
case LockMode::OPTIMISTIC === $lockMode: | ||
if ( ! $class->isVersioned) { | ||
|
@@ -540,6 +557,7 @@ public function getPartialReference($entityName, $identifier) | |
*/ | ||
public function clear($entityName = null) | ||
{ | ||
$this->persisterFactory->clear(); | ||
$this->unitOfWork->clear($entityName); | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would it be possible to avoid creating yet another circular object graph ? Given that we consider that extending the EntityManager is not supported and that we encourage using composition instead, we should try to make it actually work. Anytime we pass
$this
to another object, we are making it impossible to use composition (because we pass the inner object, not the decorator).Note that it might be very hard to do this in Doctrine 2.x (meaning that we are actually lying when saying they should decorate the EntityManager) because almost every low layers of the ORM are actually depending on the high level EntityManager (which itself depends on the lower layers)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a way to fix this, if we introduce 2 concepts:
If I could traverse between EntityBindings to get Metadata of others, its Persisters inside of an existing Persister, then yes, we could circle back these dependency hell. But it would introduce some serious cost in performance. As I said in the beginning, I'm proposing to do the bare minimum to fully support many to many extra lazy operations.
The PersisterFactory is required because a subsequent PR will be responsible to generate SQL pieces, allowing to address the currently impossible bug #1033 . This SQL class would be instantiated inside of PersisterFactory and shared between Persisters. That's the only way I found to do it without entering on a Refactoring hell of UoW, Persisters and small bits of Hydrators.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm already designing that stuff, but it's out of scope for this PR.