EntityManager.php 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752
  1. <?php
  2. /*
  3. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  4. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  5. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  6. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  7. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  8. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  9. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  10. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  11. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  12. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  13. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  14. *
  15. * This software consists of voluntary contributions made by many individuals
  16. * and is licensed under the LGPL. For more information, see
  17. * <http://www.doctrine-project.org>.
  18. */
  19. namespace Doctrine\ORM;
  20. use Closure, Exception,
  21. Doctrine\Common\EventManager,
  22. Doctrine\Common\Persistence\ObjectManager,
  23. Doctrine\DBAL\Connection,
  24. Doctrine\DBAL\LockMode,
  25. Doctrine\ORM\Mapping\ClassMetadata,
  26. Doctrine\ORM\Mapping\ClassMetadataFactory,
  27. Doctrine\ORM\Query\ResultSetMapping,
  28. Doctrine\ORM\Proxy\ProxyFactory;
  29. /**
  30. * The EntityManager is the central access point to ORM functionality.
  31. *
  32. * @since 2.0
  33. * @author Benjamin Eberlei <kontakt@beberlei.de>
  34. * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
  35. * @author Jonathan Wage <jonwage@gmail.com>
  36. * @author Roman Borschel <roman@code-factory.org>
  37. */
  38. class EntityManager implements ObjectManager
  39. {
  40. /**
  41. * The used Configuration.
  42. *
  43. * @var \Doctrine\ORM\Configuration
  44. */
  45. private $config;
  46. /**
  47. * The database connection used by the EntityManager.
  48. *
  49. * @var \Doctrine\DBAL\Connection
  50. */
  51. private $conn;
  52. /**
  53. * The metadata factory, used to retrieve the ORM metadata of entity classes.
  54. *
  55. * @var \Doctrine\ORM\Mapping\ClassMetadataFactory
  56. */
  57. private $metadataFactory;
  58. /**
  59. * The EntityRepository instances.
  60. *
  61. * @var array
  62. */
  63. private $repositories = array();
  64. /**
  65. * The UnitOfWork used to coordinate object-level transactions.
  66. *
  67. * @var \Doctrine\ORM\UnitOfWork
  68. */
  69. private $unitOfWork;
  70. /**
  71. * The event manager that is the central point of the event system.
  72. *
  73. * @var \Doctrine\Common\EventManager
  74. */
  75. private $eventManager;
  76. /**
  77. * The maintained (cached) hydrators. One instance per type.
  78. *
  79. * @var array
  80. */
  81. private $hydrators = array();
  82. /**
  83. * The proxy factory used to create dynamic proxies.
  84. *
  85. * @var \Doctrine\ORM\Proxy\ProxyFactory
  86. */
  87. private $proxyFactory;
  88. /**
  89. * The expression builder instance used to generate query expressions.
  90. *
  91. * @var \Doctrine\ORM\Query\Expr
  92. */
  93. private $expressionBuilder;
  94. /**
  95. * Whether the EntityManager is closed or not.
  96. *
  97. * @var bool
  98. */
  99. private $closed = false;
  100. /**
  101. * Creates a new EntityManager that operates on the given database connection
  102. * and uses the given Configuration and EventManager implementations.
  103. *
  104. * @param \Doctrine\DBAL\Connection $conn
  105. * @param \Doctrine\ORM\Configuration $config
  106. * @param \Doctrine\Common\EventManager $eventManager
  107. */
  108. protected function __construct(Connection $conn, Configuration $config, EventManager $eventManager)
  109. {
  110. $this->conn = $conn;
  111. $this->config = $config;
  112. $this->eventManager = $eventManager;
  113. $metadataFactoryClassName = $config->getClassMetadataFactoryName();
  114. $this->metadataFactory = new $metadataFactoryClassName;
  115. $this->metadataFactory->setEntityManager($this);
  116. $this->metadataFactory->setCacheDriver($this->config->getMetadataCacheImpl());
  117. $this->unitOfWork = new UnitOfWork($this);
  118. $this->proxyFactory = new ProxyFactory($this,
  119. $config->getProxyDir(),
  120. $config->getProxyNamespace(),
  121. $config->getAutoGenerateProxyClasses());
  122. }
  123. /**
  124. * Gets the database connection object used by the EntityManager.
  125. *
  126. * @return \Doctrine\DBAL\Connection
  127. */
  128. public function getConnection()
  129. {
  130. return $this->conn;
  131. }
  132. /**
  133. * Gets the metadata factory used to gather the metadata of classes.
  134. *
  135. * @return \Doctrine\ORM\Mapping\ClassMetadataFactory
  136. */
  137. public function getMetadataFactory()
  138. {
  139. return $this->metadataFactory;
  140. }
  141. /**
  142. * Gets an ExpressionBuilder used for object-oriented construction of query expressions.
  143. *
  144. * Example:
  145. *
  146. * <code>
  147. * $qb = $em->createQueryBuilder();
  148. * $expr = $em->getExpressionBuilder();
  149. * $qb->select('u')->from('User', 'u')
  150. * ->where($expr->orX($expr->eq('u.id', 1), $expr->eq('u.id', 2)));
  151. * </code>
  152. *
  153. * @return \Doctrine\ORM\Query\Expr
  154. */
  155. public function getExpressionBuilder()
  156. {
  157. if ($this->expressionBuilder === null) {
  158. $this->expressionBuilder = new Query\Expr;
  159. }
  160. return $this->expressionBuilder;
  161. }
  162. /**
  163. * Starts a transaction on the underlying database connection.
  164. *
  165. * @deprecated Use {@link getConnection}.beginTransaction().
  166. */
  167. public function beginTransaction()
  168. {
  169. $this->conn->beginTransaction();
  170. }
  171. /**
  172. * Executes a function in a transaction.
  173. *
  174. * The function gets passed this EntityManager instance as an (optional) parameter.
  175. *
  176. * {@link flush} is invoked prior to transaction commit.
  177. *
  178. * If an exception occurs during execution of the function or flushing or transaction commit,
  179. * the transaction is rolled back, the EntityManager closed and the exception re-thrown.
  180. *
  181. * @param Closure $func The function to execute transactionally.
  182. */
  183. public function transactional(Closure $func)
  184. {
  185. $this->conn->beginTransaction();
  186. try {
  187. $return = $func($this);
  188. $this->flush();
  189. $this->conn->commit();
  190. return $return ?: true;
  191. } catch (Exception $e) {
  192. $this->close();
  193. $this->conn->rollback();
  194. throw $e;
  195. }
  196. }
  197. /**
  198. * Commits a transaction on the underlying database connection.
  199. *
  200. * @deprecated Use {@link getConnection}.commit().
  201. */
  202. public function commit()
  203. {
  204. $this->conn->commit();
  205. }
  206. /**
  207. * Performs a rollback on the underlying database connection.
  208. *
  209. * @deprecated Use {@link getConnection}.rollback().
  210. */
  211. public function rollback()
  212. {
  213. $this->conn->rollback();
  214. }
  215. /**
  216. * Returns the ORM metadata descriptor for a class.
  217. *
  218. * The class name must be the fully-qualified class name without a leading backslash
  219. * (as it is returned by get_class($obj)) or an aliased class name.
  220. *
  221. * Examples:
  222. * MyProject\Domain\User
  223. * sales:PriceRequest
  224. *
  225. * @return \Doctrine\ORM\Mapping\ClassMetadata
  226. * @internal Performance-sensitive method.
  227. */
  228. public function getClassMetadata($className)
  229. {
  230. return $this->metadataFactory->getMetadataFor($className);
  231. }
  232. /**
  233. * Creates a new Query object.
  234. *
  235. * @param string The DQL string.
  236. * @return \Doctrine\ORM\Query
  237. */
  238. public function createQuery($dql = "")
  239. {
  240. $query = new Query($this);
  241. if ( ! empty($dql)) {
  242. $query->setDql($dql);
  243. }
  244. return $query;
  245. }
  246. /**
  247. * Creates a Query from a named query.
  248. *
  249. * @param string $name
  250. * @return \Doctrine\ORM\Query
  251. */
  252. public function createNamedQuery($name)
  253. {
  254. return $this->createQuery($this->config->getNamedQuery($name));
  255. }
  256. /**
  257. * Creates a native SQL query.
  258. *
  259. * @param string $sql
  260. * @param ResultSetMapping $rsm The ResultSetMapping to use.
  261. * @return NativeQuery
  262. */
  263. public function createNativeQuery($sql, ResultSetMapping $rsm)
  264. {
  265. $query = new NativeQuery($this);
  266. $query->setSql($sql);
  267. $query->setResultSetMapping($rsm);
  268. return $query;
  269. }
  270. /**
  271. * Creates a NativeQuery from a named native query.
  272. *
  273. * @param string $name
  274. * @return \Doctrine\ORM\NativeQuery
  275. */
  276. public function createNamedNativeQuery($name)
  277. {
  278. list($sql, $rsm) = $this->config->getNamedNativeQuery($name);
  279. return $this->createNativeQuery($sql, $rsm);
  280. }
  281. /**
  282. * Create a QueryBuilder instance
  283. *
  284. * @return QueryBuilder $qb
  285. */
  286. public function createQueryBuilder()
  287. {
  288. return new QueryBuilder($this);
  289. }
  290. /**
  291. * Flushes all changes to objects that have been queued up to now to the database.
  292. * This effectively synchronizes the in-memory state of managed objects with the
  293. * database.
  294. *
  295. * @throws \Doctrine\ORM\OptimisticLockException If a version check on an entity that
  296. * makes use of optimistic locking fails.
  297. */
  298. public function flush()
  299. {
  300. $this->errorIfClosed();
  301. $this->unitOfWork->commit();
  302. }
  303. /**
  304. * Finds an Entity by its identifier.
  305. *
  306. * This is just a convenient shortcut for getRepository($entityName)->find($id).
  307. *
  308. * @param string $entityName
  309. * @param mixed $identifier
  310. * @param int $lockMode
  311. * @param int $lockVersion
  312. * @return object
  313. */
  314. public function find($entityName, $identifier, $lockMode = LockMode::NONE, $lockVersion = null)
  315. {
  316. return $this->getRepository($entityName)->find($identifier, $lockMode, $lockVersion);
  317. }
  318. /**
  319. * Gets a reference to the entity identified by the given type and identifier
  320. * without actually loading it, if the entity is not yet loaded.
  321. *
  322. * @param string $entityName The name of the entity type.
  323. * @param mixed $identifier The entity identifier.
  324. * @return object The entity reference.
  325. */
  326. public function getReference($entityName, $identifier)
  327. {
  328. $class = $this->metadataFactory->getMetadataFor(ltrim($entityName, '\\'));
  329. // Check identity map first, if its already in there just return it.
  330. if ($entity = $this->unitOfWork->tryGetById($identifier, $class->rootEntityName)) {
  331. return ($entity instanceof $class->name) ? $entity : null;
  332. }
  333. if ($class->subClasses) {
  334. $entity = $this->find($entityName, $identifier);
  335. } else {
  336. if ( ! is_array($identifier)) {
  337. $identifier = array($class->identifier[0] => $identifier);
  338. }
  339. $entity = $this->proxyFactory->getProxy($class->name, $identifier);
  340. $this->unitOfWork->registerManaged($entity, $identifier, array());
  341. }
  342. return $entity;
  343. }
  344. /**
  345. * Gets a partial reference to the entity identified by the given type and identifier
  346. * without actually loading it, if the entity is not yet loaded.
  347. *
  348. * The returned reference may be a partial object if the entity is not yet loaded/managed.
  349. * If it is a partial object it will not initialize the rest of the entity state on access.
  350. * Thus you can only ever safely access the identifier of an entity obtained through
  351. * this method.
  352. *
  353. * The use-cases for partial references involve maintaining bidirectional associations
  354. * without loading one side of the association or to update an entity without loading it.
  355. * Note, however, that in the latter case the original (persistent) entity data will
  356. * never be visible to the application (especially not event listeners) as it will
  357. * never be loaded in the first place.
  358. *
  359. * @param string $entityName The name of the entity type.
  360. * @param mixed $identifier The entity identifier.
  361. * @return object The (partial) entity reference.
  362. */
  363. public function getPartialReference($entityName, $identifier)
  364. {
  365. $class = $this->metadataFactory->getMetadataFor(ltrim($entityName, '\\'));
  366. // Check identity map first, if its already in there just return it.
  367. if ($entity = $this->unitOfWork->tryGetById($identifier, $class->rootEntityName)) {
  368. return ($entity instanceof $class->name) ? $entity : null;
  369. }
  370. if ( ! is_array($identifier)) {
  371. $identifier = array($class->identifier[0] => $identifier);
  372. }
  373. $entity = $class->newInstance();
  374. $class->setIdentifierValues($entity, $identifier);
  375. $this->unitOfWork->registerManaged($entity, $identifier, array());
  376. $this->unitOfWork->markReadOnly($entity);
  377. return $entity;
  378. }
  379. /**
  380. * Clears the EntityManager. All entities that are currently managed
  381. * by this EntityManager become detached.
  382. *
  383. * @param string $entityName
  384. */
  385. public function clear($entityName = null)
  386. {
  387. if ($entityName === null) {
  388. $this->unitOfWork->clear();
  389. } else {
  390. //TODO
  391. throw new ORMException("EntityManager#clear(\$entityName) not yet implemented.");
  392. }
  393. }
  394. /**
  395. * Closes the EntityManager. All entities that are currently managed
  396. * by this EntityManager become detached. The EntityManager may no longer
  397. * be used after it is closed.
  398. */
  399. public function close()
  400. {
  401. $this->clear();
  402. $this->closed = true;
  403. }
  404. /**
  405. * Tells the EntityManager to make an instance managed and persistent.
  406. *
  407. * The entity will be entered into the database at or before transaction
  408. * commit or as a result of the flush operation.
  409. *
  410. * NOTE: The persist operation always considers entities that are not yet known to
  411. * this EntityManager as NEW. Do not pass detached entities to the persist operation.
  412. *
  413. * @param object $object The instance to make managed and persistent.
  414. */
  415. public function persist($entity)
  416. {
  417. if ( ! is_object($entity)) {
  418. throw new \InvalidArgumentException(gettype($entity));
  419. }
  420. $this->errorIfClosed();
  421. $this->unitOfWork->persist($entity);
  422. }
  423. /**
  424. * Removes an entity instance.
  425. *
  426. * A removed entity will be removed from the database at or before transaction commit
  427. * or as a result of the flush operation.
  428. *
  429. * @param object $entity The entity instance to remove.
  430. */
  431. public function remove($entity)
  432. {
  433. if ( ! is_object($entity)) {
  434. throw new \InvalidArgumentException(gettype($entity));
  435. }
  436. $this->errorIfClosed();
  437. $this->unitOfWork->remove($entity);
  438. }
  439. /**
  440. * Refreshes the persistent state of an entity from the database,
  441. * overriding any local changes that have not yet been persisted.
  442. *
  443. * @param object $entity The entity to refresh.
  444. */
  445. public function refresh($entity)
  446. {
  447. if ( ! is_object($entity)) {
  448. throw new \InvalidArgumentException(gettype($entity));
  449. }
  450. $this->errorIfClosed();
  451. $this->unitOfWork->refresh($entity);
  452. }
  453. /**
  454. * Detaches an entity from the EntityManager, causing a managed entity to
  455. * become detached. Unflushed changes made to the entity if any
  456. * (including removal of the entity), will not be synchronized to the database.
  457. * Entities which previously referenced the detached entity will continue to
  458. * reference it.
  459. *
  460. * @param object $entity The entity to detach.
  461. */
  462. public function detach($entity)
  463. {
  464. if ( ! is_object($entity)) {
  465. throw new \InvalidArgumentException(gettype($entity));
  466. }
  467. $this->unitOfWork->detach($entity);
  468. }
  469. /**
  470. * Merges the state of a detached entity into the persistence context
  471. * of this EntityManager and returns the managed copy of the entity.
  472. * The entity passed to merge will not become associated/managed with this EntityManager.
  473. *
  474. * @param object $entity The detached entity to merge into the persistence context.
  475. * @return object The managed copy of the entity.
  476. */
  477. public function merge($entity)
  478. {
  479. if ( ! is_object($entity)) {
  480. throw new \InvalidArgumentException(gettype($entity));
  481. }
  482. $this->errorIfClosed();
  483. return $this->unitOfWork->merge($entity);
  484. }
  485. /**
  486. * Creates a copy of the given entity. Can create a shallow or a deep copy.
  487. *
  488. * @param object $entity The entity to copy.
  489. * @return object The new entity.
  490. * @todo Implementation need. This is necessary since $e2 = clone $e1; throws an E_FATAL when access anything on $e:
  491. * Fatal error: Maximum function nesting level of '100' reached, aborting!
  492. */
  493. public function copy($entity, $deep = false)
  494. {
  495. throw new \BadMethodCallException("Not implemented.");
  496. }
  497. /**
  498. * Acquire a lock on the given entity.
  499. *
  500. * @param object $entity
  501. * @param int $lockMode
  502. * @param int $lockVersion
  503. * @throws OptimisticLockException
  504. * @throws PessimisticLockException
  505. */
  506. public function lock($entity, $lockMode, $lockVersion = null)
  507. {
  508. $this->unitOfWork->lock($entity, $lockMode, $lockVersion);
  509. }
  510. /**
  511. * Gets the repository for an entity class.
  512. *
  513. * @param string $entityName The name of the entity.
  514. * @return EntityRepository The repository class.
  515. */
  516. public function getRepository($entityName)
  517. {
  518. $entityName = ltrim($entityName, '\\');
  519. if (isset($this->repositories[$entityName])) {
  520. return $this->repositories[$entityName];
  521. }
  522. $metadata = $this->getClassMetadata($entityName);
  523. $customRepositoryClassName = $metadata->customRepositoryClassName;
  524. if ($customRepositoryClassName !== null) {
  525. $repository = new $customRepositoryClassName($this, $metadata);
  526. } else {
  527. $repository = new EntityRepository($this, $metadata);
  528. }
  529. $this->repositories[$entityName] = $repository;
  530. return $repository;
  531. }
  532. /**
  533. * Determines whether an entity instance is managed in this EntityManager.
  534. *
  535. * @param object $entity
  536. * @return boolean TRUE if this EntityManager currently manages the given entity, FALSE otherwise.
  537. */
  538. public function contains($entity)
  539. {
  540. return $this->unitOfWork->isScheduledForInsert($entity) ||
  541. $this->unitOfWork->isInIdentityMap($entity) &&
  542. ! $this->unitOfWork->isScheduledForDelete($entity);
  543. }
  544. /**
  545. * Gets the EventManager used by the EntityManager.
  546. *
  547. * @return \Doctrine\Common\EventManager
  548. */
  549. public function getEventManager()
  550. {
  551. return $this->eventManager;
  552. }
  553. /**
  554. * Gets the Configuration used by the EntityManager.
  555. *
  556. * @return \Doctrine\ORM\Configuration
  557. */
  558. public function getConfiguration()
  559. {
  560. return $this->config;
  561. }
  562. /**
  563. * Throws an exception if the EntityManager is closed or currently not active.
  564. *
  565. * @throws ORMException If the EntityManager is closed.
  566. */
  567. private function errorIfClosed()
  568. {
  569. if ($this->closed) {
  570. throw ORMException::entityManagerClosed();
  571. }
  572. }
  573. /**
  574. * Check if the Entity manager is open or closed.
  575. *
  576. * @return bool
  577. */
  578. public function isOpen()
  579. {
  580. return (!$this->closed);
  581. }
  582. /**
  583. * Gets the UnitOfWork used by the EntityManager to coordinate operations.
  584. *
  585. * @return \Doctrine\ORM\UnitOfWork
  586. */
  587. public function getUnitOfWork()
  588. {
  589. return $this->unitOfWork;
  590. }
  591. /**
  592. * Gets a hydrator for the given hydration mode.
  593. *
  594. * This method caches the hydrator instances which is used for all queries that don't
  595. * selectively iterate over the result.
  596. *
  597. * @param int $hydrationMode
  598. * @return \Doctrine\ORM\Internal\Hydration\AbstractHydrator
  599. */
  600. public function getHydrator($hydrationMode)
  601. {
  602. if ( ! isset($this->hydrators[$hydrationMode])) {
  603. $this->hydrators[$hydrationMode] = $this->newHydrator($hydrationMode);
  604. }
  605. return $this->hydrators[$hydrationMode];
  606. }
  607. /**
  608. * Create a new instance for the given hydration mode.
  609. *
  610. * @param int $hydrationMode
  611. * @return \Doctrine\ORM\Internal\Hydration\AbstractHydrator
  612. */
  613. public function newHydrator($hydrationMode)
  614. {
  615. switch ($hydrationMode) {
  616. case Query::HYDRATE_OBJECT:
  617. $hydrator = new Internal\Hydration\ObjectHydrator($this);
  618. break;
  619. case Query::HYDRATE_ARRAY:
  620. $hydrator = new Internal\Hydration\ArrayHydrator($this);
  621. break;
  622. case Query::HYDRATE_SCALAR:
  623. $hydrator = new Internal\Hydration\ScalarHydrator($this);
  624. break;
  625. case Query::HYDRATE_SINGLE_SCALAR:
  626. $hydrator = new Internal\Hydration\SingleScalarHydrator($this);
  627. break;
  628. case Query::HYDRATE_SIMPLEOBJECT:
  629. $hydrator = new Internal\Hydration\SimpleObjectHydrator($this);
  630. break;
  631. default:
  632. if ($class = $this->config->getCustomHydrationMode($hydrationMode)) {
  633. $hydrator = new $class($this);
  634. break;
  635. }
  636. throw ORMException::invalidHydrationMode($hydrationMode);
  637. }
  638. return $hydrator;
  639. }
  640. /**
  641. * Gets the proxy factory used by the EntityManager to create entity proxies.
  642. *
  643. * @return ProxyFactory
  644. */
  645. public function getProxyFactory()
  646. {
  647. return $this->proxyFactory;
  648. }
  649. /**
  650. * {@inheritDoc}
  651. */
  652. public function initializeObject($entity)
  653. {
  654. $this->unitOfWork->initializeObject($entity);
  655. }
  656. /**
  657. * Factory method to create EntityManager instances.
  658. *
  659. * @param mixed $conn An array with the connection parameters or an existing
  660. * Connection instance.
  661. * @param Configuration $config The Configuration instance to use.
  662. * @param EventManager $eventManager The EventManager instance to use.
  663. * @return EntityManager The created EntityManager.
  664. */
  665. public static function create($conn, Configuration $config, EventManager $eventManager = null)
  666. {
  667. if (!$config->getMetadataDriverImpl()) {
  668. throw ORMException::missingMappingDriverImpl();
  669. }
  670. if (is_array($conn)) {
  671. $conn = \Doctrine\DBAL\DriverManager::getConnection($conn, $config, ($eventManager ?: new EventManager()));
  672. } else if ($conn instanceof Connection) {
  673. if ($eventManager !== null && $conn->getEventManager() !== $eventManager) {
  674. throw ORMException::mismatchedEventManager();
  675. }
  676. } else {
  677. throw new \InvalidArgumentException("Invalid argument: " . $conn);
  678. }
  679. return new EntityManager($conn, $config, $conn->getEventManager());
  680. }
  681. }