EntityManager.php 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743
  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. return $entity;
  377. }
  378. /**
  379. * Clears the EntityManager. All entities that are currently managed
  380. * by this EntityManager become detached.
  381. *
  382. * @param string $entityName
  383. */
  384. public function clear($entityName = null)
  385. {
  386. if ($entityName === null) {
  387. $this->unitOfWork->clear();
  388. } else {
  389. //TODO
  390. throw new ORMException("EntityManager#clear(\$entityName) not yet implemented.");
  391. }
  392. }
  393. /**
  394. * Closes the EntityManager. All entities that are currently managed
  395. * by this EntityManager become detached. The EntityManager may no longer
  396. * be used after it is closed.
  397. */
  398. public function close()
  399. {
  400. $this->clear();
  401. $this->closed = true;
  402. }
  403. /**
  404. * Tells the EntityManager to make an instance managed and persistent.
  405. *
  406. * The entity will be entered into the database at or before transaction
  407. * commit or as a result of the flush operation.
  408. *
  409. * NOTE: The persist operation always considers entities that are not yet known to
  410. * this EntityManager as NEW. Do not pass detached entities to the persist operation.
  411. *
  412. * @param object $object The instance to make managed and persistent.
  413. */
  414. public function persist($entity)
  415. {
  416. if ( ! is_object($entity)) {
  417. throw new \InvalidArgumentException(gettype($entity));
  418. }
  419. $this->errorIfClosed();
  420. $this->unitOfWork->persist($entity);
  421. }
  422. /**
  423. * Removes an entity instance.
  424. *
  425. * A removed entity will be removed from the database at or before transaction commit
  426. * or as a result of the flush operation.
  427. *
  428. * @param object $entity The entity instance to remove.
  429. */
  430. public function remove($entity)
  431. {
  432. if ( ! is_object($entity)) {
  433. throw new \InvalidArgumentException(gettype($entity));
  434. }
  435. $this->errorIfClosed();
  436. $this->unitOfWork->remove($entity);
  437. }
  438. /**
  439. * Refreshes the persistent state of an entity from the database,
  440. * overriding any local changes that have not yet been persisted.
  441. *
  442. * @param object $entity The entity to refresh.
  443. */
  444. public function refresh($entity)
  445. {
  446. if ( ! is_object($entity)) {
  447. throw new \InvalidArgumentException(gettype($entity));
  448. }
  449. $this->errorIfClosed();
  450. $this->unitOfWork->refresh($entity);
  451. }
  452. /**
  453. * Detaches an entity from the EntityManager, causing a managed entity to
  454. * become detached. Unflushed changes made to the entity if any
  455. * (including removal of the entity), will not be synchronized to the database.
  456. * Entities which previously referenced the detached entity will continue to
  457. * reference it.
  458. *
  459. * @param object $entity The entity to detach.
  460. */
  461. public function detach($entity)
  462. {
  463. if ( ! is_object($entity)) {
  464. throw new \InvalidArgumentException(gettype($entity));
  465. }
  466. $this->unitOfWork->detach($entity);
  467. }
  468. /**
  469. * Merges the state of a detached entity into the persistence context
  470. * of this EntityManager and returns the managed copy of the entity.
  471. * The entity passed to merge will not become associated/managed with this EntityManager.
  472. *
  473. * @param object $entity The detached entity to merge into the persistence context.
  474. * @return object The managed copy of the entity.
  475. */
  476. public function merge($entity)
  477. {
  478. if ( ! is_object($entity)) {
  479. throw new \InvalidArgumentException(gettype($entity));
  480. }
  481. $this->errorIfClosed();
  482. return $this->unitOfWork->merge($entity);
  483. }
  484. /**
  485. * Creates a copy of the given entity. Can create a shallow or a deep copy.
  486. *
  487. * @param object $entity The entity to copy.
  488. * @return object The new entity.
  489. * @todo Implementation need. This is necessary since $e2 = clone $e1; throws an E_FATAL when access anything on $e:
  490. * Fatal error: Maximum function nesting level of '100' reached, aborting!
  491. */
  492. public function copy($entity, $deep = false)
  493. {
  494. throw new \BadMethodCallException("Not implemented.");
  495. }
  496. /**
  497. * Acquire a lock on the given entity.
  498. *
  499. * @param object $entity
  500. * @param int $lockMode
  501. * @param int $lockVersion
  502. * @throws OptimisticLockException
  503. * @throws PessimisticLockException
  504. */
  505. public function lock($entity, $lockMode, $lockVersion = null)
  506. {
  507. $this->unitOfWork->lock($entity, $lockMode, $lockVersion);
  508. }
  509. /**
  510. * Gets the repository for an entity class.
  511. *
  512. * @param string $entityName The name of the entity.
  513. * @return EntityRepository The repository class.
  514. */
  515. public function getRepository($entityName)
  516. {
  517. $entityName = ltrim($entityName, '\\');
  518. if (isset($this->repositories[$entityName])) {
  519. return $this->repositories[$entityName];
  520. }
  521. $metadata = $this->getClassMetadata($entityName);
  522. $customRepositoryClassName = $metadata->customRepositoryClassName;
  523. if ($customRepositoryClassName !== null) {
  524. $repository = new $customRepositoryClassName($this, $metadata);
  525. } else {
  526. $repository = new EntityRepository($this, $metadata);
  527. }
  528. $this->repositories[$entityName] = $repository;
  529. return $repository;
  530. }
  531. /**
  532. * Determines whether an entity instance is managed in this EntityManager.
  533. *
  534. * @param object $entity
  535. * @return boolean TRUE if this EntityManager currently manages the given entity, FALSE otherwise.
  536. */
  537. public function contains($entity)
  538. {
  539. return $this->unitOfWork->isScheduledForInsert($entity) ||
  540. $this->unitOfWork->isInIdentityMap($entity) &&
  541. ! $this->unitOfWork->isScheduledForDelete($entity);
  542. }
  543. /**
  544. * Gets the EventManager used by the EntityManager.
  545. *
  546. * @return Doctrine\Common\EventManager
  547. */
  548. public function getEventManager()
  549. {
  550. return $this->eventManager;
  551. }
  552. /**
  553. * Gets the Configuration used by the EntityManager.
  554. *
  555. * @return Doctrine\ORM\Configuration
  556. */
  557. public function getConfiguration()
  558. {
  559. return $this->config;
  560. }
  561. /**
  562. * Throws an exception if the EntityManager is closed or currently not active.
  563. *
  564. * @throws ORMException If the EntityManager is closed.
  565. */
  566. private function errorIfClosed()
  567. {
  568. if ($this->closed) {
  569. throw ORMException::entityManagerClosed();
  570. }
  571. }
  572. /**
  573. * Check if the Entity manager is open or closed.
  574. *
  575. * @return bool
  576. */
  577. public function isOpen()
  578. {
  579. return (!$this->closed);
  580. }
  581. /**
  582. * Gets the UnitOfWork used by the EntityManager to coordinate operations.
  583. *
  584. * @return Doctrine\ORM\UnitOfWork
  585. */
  586. public function getUnitOfWork()
  587. {
  588. return $this->unitOfWork;
  589. }
  590. /**
  591. * Gets a hydrator for the given hydration mode.
  592. *
  593. * This method caches the hydrator instances which is used for all queries that don't
  594. * selectively iterate over the result.
  595. *
  596. * @param int $hydrationMode
  597. * @return Doctrine\ORM\Internal\Hydration\AbstractHydrator
  598. */
  599. public function getHydrator($hydrationMode)
  600. {
  601. if ( ! isset($this->hydrators[$hydrationMode])) {
  602. $this->hydrators[$hydrationMode] = $this->newHydrator($hydrationMode);
  603. }
  604. return $this->hydrators[$hydrationMode];
  605. }
  606. /**
  607. * Create a new instance for the given hydration mode.
  608. *
  609. * @param int $hydrationMode
  610. * @return Doctrine\ORM\Internal\Hydration\AbstractHydrator
  611. */
  612. public function newHydrator($hydrationMode)
  613. {
  614. switch ($hydrationMode) {
  615. case Query::HYDRATE_OBJECT:
  616. $hydrator = new Internal\Hydration\ObjectHydrator($this);
  617. break;
  618. case Query::HYDRATE_ARRAY:
  619. $hydrator = new Internal\Hydration\ArrayHydrator($this);
  620. break;
  621. case Query::HYDRATE_SCALAR:
  622. $hydrator = new Internal\Hydration\ScalarHydrator($this);
  623. break;
  624. case Query::HYDRATE_SINGLE_SCALAR:
  625. $hydrator = new Internal\Hydration\SingleScalarHydrator($this);
  626. break;
  627. case Query::HYDRATE_SIMPLEOBJECT:
  628. $hydrator = new Internal\Hydration\SimpleObjectHydrator($this);
  629. break;
  630. default:
  631. if ($class = $this->config->getCustomHydrationMode($hydrationMode)) {
  632. $hydrator = new $class($this);
  633. break;
  634. }
  635. throw ORMException::invalidHydrationMode($hydrationMode);
  636. }
  637. return $hydrator;
  638. }
  639. /**
  640. * Gets the proxy factory used by the EntityManager to create entity proxies.
  641. *
  642. * @return ProxyFactory
  643. */
  644. public function getProxyFactory()
  645. {
  646. return $this->proxyFactory;
  647. }
  648. /**
  649. * Factory method to create EntityManager instances.
  650. *
  651. * @param mixed $conn An array with the connection parameters or an existing
  652. * Connection instance.
  653. * @param Configuration $config The Configuration instance to use.
  654. * @param EventManager $eventManager The EventManager instance to use.
  655. * @return EntityManager The created EntityManager.
  656. */
  657. public static function create($conn, Configuration $config, EventManager $eventManager = null)
  658. {
  659. if (!$config->getMetadataDriverImpl()) {
  660. throw ORMException::missingMappingDriverImpl();
  661. }
  662. if (is_array($conn)) {
  663. $conn = \Doctrine\DBAL\DriverManager::getConnection($conn, $config, ($eventManager ?: new EventManager()));
  664. } else if ($conn instanceof Connection) {
  665. if ($eventManager !== null && $conn->getEventManager() !== $eventManager) {
  666. throw ORMException::mismatchedEventManager();
  667. }
  668. } else {
  669. throw new \InvalidArgumentException("Invalid argument: " . $conn);
  670. }
  671. return new EntityManager($conn, $config, $conn->getEventManager());
  672. }
  673. }