working-with-objects.rst 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850
  1. Working with Objects
  2. ====================
  3. In this chapter we will help you understand the ``EntityManager``
  4. and the ``UnitOfWork``. A Unit of Work is similar to an
  5. object-level transaction. A new Unit of Work is implicitly started
  6. when an EntityManager is initially created or after
  7. ``EntityManager#flush()`` has been invoked. A Unit of Work is
  8. committed (and a new one started) by invoking
  9. ``EntityManager#flush()``.
  10. A Unit of Work can be manually closed by calling
  11. EntityManager#close(). Any changes to objects within this Unit of
  12. Work that have not yet been persisted are lost.
  13. .. note::
  14. It is very important to understand that only
  15. ``EntityManager#flush()`` ever causes write operations against the
  16. database to be executed. Any other methods such as
  17. ``EntityManager#persist($entity)`` or
  18. ``EntityManager#remove($entity)`` only notify the UnitOfWork to
  19. perform these operations during flush.
  20. Not calling ``EntityManager#flush()`` will lead to all changes
  21. during that request being lost.
  22. Entities and the Identity Map
  23. -----------------------------
  24. Entities are objects with identity. Their identity has a conceptual
  25. meaning inside your domain. In a CMS application each article has a
  26. unique id. You can uniquely identify each article by that id.
  27. Take the following example, where you find an article with the
  28. headline "Hello World" with the ID 1234:
  29. .. code-block:: php
  30. <?php
  31. $article = $entityManager->find('CMS\Article', 1234);
  32. $article->setHeadline('Hello World dude!');
  33. $article2 = $entityManager->find('CMS\Article', 1234);
  34. echo $article2->getHeadline();
  35. In this case the Article is accessed from the entity manager twice,
  36. but modified in between. Doctrine 2 realizes this and will only
  37. ever give you access to one instance of the Article with ID 1234,
  38. no matter how often do you retrieve it from the EntityManager and
  39. even no matter what kind of Query method you are using (find,
  40. Repository Finder or DQL). This is called "Identity Map" pattern,
  41. which means Doctrine keeps a map of each entity and ids that have
  42. been retrieved per PHP request and keeps returning you the same
  43. instances.
  44. In the previous example the echo prints "Hello World dude!" to the
  45. screen. You can even verify that ``$article`` and ``$article2`` are
  46. indeed pointing to the same instance by running the following
  47. code:
  48. .. code-block:: php
  49. <?php
  50. if ($article === $article2) {
  51. echo "Yes we are the same!";
  52. }
  53. Sometimes you want to clear the identity map of an EntityManager to
  54. start over. We use this regularly in our unit-tests to enforce
  55. loading objects from the database again instead of serving them
  56. from the identity map. You can call ``EntityManager#clear()`` to
  57. achieve this result.
  58. Entity Object Graph Traversal
  59. -----------------------------
  60. Although Doctrine allows for a complete separation of your domain
  61. model (Entity classes) there will never be a situation where
  62. objects are "missing" when traversing associations. You can walk
  63. all the associations inside your entity models as deep as you
  64. want.
  65. Take the following example of a single ``Article`` entity fetched
  66. from newly opened EntityManager.
  67. .. code-block:: php
  68. <?php
  69. /** @Entity */
  70. class Article
  71. {
  72. /** @Id @Column(type="integer") @GeneratedValue */
  73. private $id;
  74. /** @Column(type="string") */
  75. private $headline;
  76. /** @ManyToOne(targetEntity="User") */
  77. private $author;
  78. /** @OneToMany(targetEntity="Comment", mappedBy="article") */
  79. private $comments;
  80. public function __construct {
  81. $this->comments = new ArrayCollection();
  82. }
  83. public function getAuthor() { return $this->author; }
  84. public function getComments() { return $this->comments; }
  85. }
  86. $article = $em->find('Article', 1);
  87. This code only retrieves the ``Article`` instance with id 1 executing
  88. a single SELECT statement against the user table in the database.
  89. You can still access the associated properties author and comments
  90. and the associated objects they contain.
  91. This works by utilizing the lazy loading pattern. Instead of
  92. passing you back a real Author instance and a collection of
  93. comments Doctrine will create proxy instances for you. Only if you
  94. access these proxies for the first time they will go through the
  95. EntityManager and load their state from the database.
  96. This lazy-loading process happens behind the scenes, hidden from
  97. your code. See the following code:
  98. .. code-block:: php
  99. <?php
  100. $article = $em->find('Article', 1);
  101. // accessing a method of the user instance triggers the lazy-load
  102. echo "Author: " . $article->getAuthor()->getName() . "\n";
  103. // Lazy Loading Proxies pass instanceof tests:
  104. if ($article->getAuthor() instanceof User) {
  105. // a User Proxy is a generated "UserProxy" class
  106. }
  107. // accessing the comments as an iterator triggers the lazy-load
  108. // retrieving ALL the comments of this article from the database
  109. // using a single SELECT statement
  110. foreach ($article->getComments() AS $comment) {
  111. echo $comment->getText() . "\n\n";
  112. }
  113. // Article::$comments passes instanceof tests for the Collection interface
  114. // But it will NOT pass for the ArrayCollection interface
  115. if ($article->getComments() instanceof \Doctrine\Common\Collections\Collection) {
  116. echo "This will always be true!";
  117. }
  118. A slice of the generated proxy classes code looks like the
  119. following piece of code. A real proxy class override ALL public
  120. methods along the lines of the ``getName()`` method shown below:
  121. .. code-block:: php
  122. <?php
  123. class UserProxy extends User implements Proxy
  124. {
  125. private function _load()
  126. {
  127. // lazy loading code
  128. }
  129. public function getName()
  130. {
  131. $this->_load();
  132. return parent::getName();
  133. }
  134. // .. other public methods of User
  135. }
  136. .. warning::
  137. Traversing the object graph for parts that are lazy-loaded will
  138. easily trigger lots of SQL queries and will perform badly if used
  139. to heavily. Make sure to use DQL to fetch-join all the parts of the
  140. object-graph that you need as efficiently as possible.
  141. Persisting entities
  142. -------------------
  143. An entity can be made persistent by passing it to the
  144. ``EntityManager#persist($entity)`` method. By applying the persist
  145. operation on some entity, that entity becomes MANAGED, which means
  146. that its persistence is from now on managed by an EntityManager. As
  147. a result the persistent state of such an entity will subsequently
  148. be properly synchronized with the database when
  149. ``EntityManager#flush()`` is invoked.
  150. .. note::
  151. Invoking the ``persist`` method on an entity does NOT
  152. cause an immediate SQL INSERT to be issued on the database.
  153. Doctrine applies a strategy called "transactional write-behind",
  154. which means that it will delay most SQL commands until
  155. ``EntityManager#flush()`` is invoked which will then issue all
  156. necessary SQL statements to synchronize your objects with the
  157. database in the most efficient way and a single, short transaction,
  158. taking care of maintaining referential integrity.
  159. Example:
  160. .. code-block:: php
  161. <?php
  162. $user = new User;
  163. $user->setName('Mr.Right');
  164. $em->persist($user);
  165. $em->flush();
  166. .. note::
  167. Generated entity identifiers / primary keys are
  168. guaranteed to be available after the next successful flush
  169. operation that involves the entity in question. You can not rely on
  170. a generated identifier to be available directly after invoking
  171. ``persist``. The inverse is also true. You can not rely on a
  172. generated identifier being not available after a failed flush
  173. operation.
  174. The semantics of the persist operation, applied on an entity X, are
  175. as follows:
  176. - If X is a new entity, it becomes managed. The entity X will be
  177. entered into the database as a result of the flush operation.
  178. - If X is a preexisting managed entity, it is ignored by the
  179. persist operation. However, the persist operation is cascaded to
  180. entities referenced by X, if the relationships from X to these
  181. other entities are mapped with cascade=PERSIST or cascade=ALL (see
  182. "Transitive Persistence").
  183. - If X is a removed entity, it becomes managed.
  184. - If X is a detached entity, an exception will be thrown on
  185. flush.
  186. Removing entities
  187. -----------------
  188. An entity can be removed from persistent storage by passing it to
  189. the ``EntityManager#remove($entity)`` method. By applying the
  190. ``remove`` operation on some entity, that entity becomes REMOVED,
  191. which means that its persistent state will be deleted once
  192. ``EntityManager#flush()`` is invoked.
  193. .. note::
  194. Just like ``persist``, invoking ``remove`` on an entity
  195. does NOT cause an immediate SQL DELETE to be issued on the
  196. database. The entity will be deleted on the next invocation of
  197. ``EntityManager#flush()`` that involves that entity. This
  198. means that entities scheduled for removal can still be queried
  199. for and appear in query and collection results. See
  200. the section on :ref:`Database and UnitOfWork Out-Of-Sync <workingobjects_database_uow_outofsync>`
  201. for more information.
  202. Example:
  203. .. code-block:: php
  204. <?php
  205. $em->remove($user);
  206. $em->flush();
  207. The semantics of the remove operation, applied to an entity X are
  208. as follows:
  209. - If X is a new entity, it is ignored by the remove operation.
  210. However, the remove operation is cascaded to entities referenced by
  211. X, if the relationship from X to these other entities is mapped
  212. with cascade=REMOVE or cascade=ALL (see "Transitive Persistence").
  213. - If X is a managed entity, the remove operation causes it to
  214. become removed. The remove operation is cascaded to entities
  215. referenced by X, if the relationships from X to these other
  216. entities is mapped with cascade=REMOVE or cascade=ALL (see
  217. "Transitive Persistence").
  218. - If X is a detached entity, an InvalidArgumentException will be
  219. thrown.
  220. - If X is a removed entity, it is ignored by the remove operation.
  221. - A removed entity X will be removed from the database as a result
  222. of the flush operation.
  223. After an entity has been removed its in-memory state is the same as
  224. before the removal, except for generated identifiers.
  225. Removing an entity will also automatically delete any existing
  226. records in many-to-many join tables that link this entity. The
  227. action taken depends on the value of the ``@joinColumn`` mapping
  228. attribute "onDelete". Either Doctrine issues a dedicated ``DELETE``
  229. statement for records of each join table or it depends on the
  230. foreign key semantics of onDelete="CASCADE".
  231. Deleting an object with all its associated objects can be achieved
  232. in multiple ways with very different performance impacts.
  233. 1. If an association is marked as ``CASCADE=REMOVE`` Doctrine 2
  234. will fetch this association. If its a Single association it will
  235. pass this entity to
  236. ´EntityManager#remove()``. If the association is a collection, Doctrine will loop over all its elements and pass them to``EntityManager#remove()\`.
  237. In both cases the cascade remove semantics are applied recursively.
  238. For large object graphs this removal strategy can be very costly.
  239. 2. Using a DQL ``DELETE`` statement allows you to delete multiple
  240. entities of a type with a single command and without hydrating
  241. these entities. This can be very efficient to delete large object
  242. graphs from the database.
  243. 3. Using foreign key semantics ``onDelete="CASCADE"`` can force the
  244. database to remove all associated objects internally. This strategy
  245. is a bit tricky to get right but can be very powerful and fast. You
  246. should be aware however that using strategy 1 (``CASCADE=REMOVE``)
  247. completely by-passes any foreign key ``onDelete=CASCADE`` option,
  248. because Doctrine will fetch and remove all associated entities
  249. explicitly nevertheless.
  250. Detaching entities
  251. ------------------
  252. An entity is detached from an EntityManager and thus no longer
  253. managed by invoking the ``EntityManager#detach($entity)`` method on
  254. it or by cascading the detach operation to it. Changes made to the
  255. detached entity, if any (including removal of the entity), will not
  256. be synchronized to the database after the entity has been
  257. detached.
  258. Doctrine will not hold on to any references to a detached entity.
  259. Example:
  260. .. code-block:: php
  261. <?php
  262. $em->detach($entity);
  263. The semantics of the detach operation, applied to an entity X are
  264. as follows:
  265. - If X is a managed entity, the detach operation causes it to
  266. become detached. The detach operation is cascaded to entities
  267. referenced by X, if the relationships from X to these other
  268. entities is mapped with cascade=DETACH or cascade=ALL (see
  269. "Transitive Persistence"). Entities which previously referenced X
  270. will continue to reference X.
  271. - If X is a new or detached entity, it is ignored by the detach
  272. operation.
  273. - If X is a removed entity, the detach operation is cascaded to
  274. entities referenced by X, if the relationships from X to these
  275. other entities is mapped with cascade=DETACH or cascade=ALL (see
  276. "Transitive Persistence"). Entities which previously referenced X
  277. will continue to reference X.
  278. There are several situations in which an entity is detached
  279. automatically without invoking the ``detach`` method:
  280. - When ``EntityManager#clear()`` is invoked, all entities that are
  281. currently managed by the EntityManager instance become detached.
  282. - When serializing an entity. The entity retrieved upon subsequent
  283. unserialization will be detached (This is the case for all entities
  284. that are serialized and stored in some cache, i.e. when using the
  285. Query Result Cache).
  286. The ``detach`` operation is usually not as frequently needed and
  287. used as ``persist`` and ``remove``.
  288. Merging entities
  289. ----------------
  290. Merging entities refers to the merging of (usually detached)
  291. entities into the context of an EntityManager so that they become
  292. managed again. To merge the state of an entity into an
  293. EntityManager use the ``EntityManager#merge($entity)`` method. The
  294. state of the passed entity will be merged into a managed copy of
  295. this entity and this copy will subsequently be returned.
  296. Example:
  297. .. code-block:: php
  298. <?php
  299. $detachedEntity = unserialize($serializedEntity); // some detached entity
  300. $entity = $em->merge($detachedEntity);
  301. // $entity now refers to the fully managed copy returned by the merge operation.
  302. // The EntityManager $em now manages the persistence of $entity as usual.
  303. .. note::
  304. When you want to serialize/unserialize entities you
  305. have to make all entity properties protected, never private. The
  306. reason for this is, if you serialize a class that was a proxy
  307. instance before, the private variables won't be serialized and a
  308. PHP Notice is thrown.
  309. The semantics of the merge operation, applied to an entity X, are
  310. as follows:
  311. - If X is a detached entity, the state of X is copied onto a
  312. pre-existing managed entity instance X' of the same identity.
  313. - If X is a new entity instance, a new managed copy X' will be
  314. created and the state of X is copied onto this managed instance.
  315. - If X is a removed entity instance, an InvalidArgumentException
  316. will be thrown.
  317. - If X is a managed entity, it is ignored by the merge operation,
  318. however, the merge operation is cascaded to entities referenced by
  319. relationships from X if these relationships have been mapped with
  320. the cascade element value MERGE or ALL (see "Transitive
  321. Persistence").
  322. - For all entities Y referenced by relationships from X having the
  323. cascade element value MERGE or ALL, Y is merged recursively as Y'.
  324. For all such Y referenced by X, X' is set to reference Y'. (Note
  325. that if X is managed then X is the same object as X'.)
  326. - If X is an entity merged to X', with a reference to another
  327. entity Y, where cascade=MERGE or cascade=ALL is not specified, then
  328. navigation of the same association from X' yields a reference to a
  329. managed object Y' with the same persistent identity as Y.
  330. The ``merge`` operation will throw an ``OptimisticLockException``
  331. if the entity being merged uses optimistic locking through a
  332. version field and the versions of the entity being merged and the
  333. managed copy don't match. This usually means that the entity has
  334. been modified while being detached.
  335. The ``merge`` operation is usually not as frequently needed and
  336. used as ``persist`` and ``remove``. The most common scenario for
  337. the ``merge`` operation is to reattach entities to an EntityManager
  338. that come from some cache (and are therefore detached) and you want
  339. to modify and persist such an entity.
  340. .. warning::
  341. If you need to perform multiple merges of entities that share certain subparts
  342. of their object-graphs and cascade merge, then you have to call ``EntityManager#clear()`` between the
  343. successive calls to ``EntityManager#merge()``. Otherwise you might end up with
  344. multiple copies of the "same" object in the database, however with different ids.
  345. .. note::
  346. If you load some detached entities from a cache and you do
  347. not need to persist or delete them or otherwise make use of them
  348. without the need for persistence services there is no need to use
  349. ``merge``. I.e. you can simply pass detached objects from a cache
  350. directly to the view.
  351. Synchronization with the Database
  352. ---------------------------------
  353. The state of persistent entities is synchronized with the database
  354. on flush of an ``EntityManager`` which commits the underlying
  355. ``UnitOfWork``. The synchronization involves writing any updates to
  356. persistent entities and their relationships to the database.
  357. Thereby bidirectional relationships are persisted based on the
  358. references held by the owning side of the relationship as explained
  359. in the Association Mapping chapter.
  360. When ``EntityManager#flush()`` is called, Doctrine inspects all
  361. managed, new and removed entities and will perform the following
  362. operations.
  363. .. _workingobjects_database_uow_outofsync:
  364. Effects of Database and UnitOfWork being Out-Of-Sync
  365. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  366. As soon as you begin to change the state of entities, call persist or remove the
  367. contents of the UnitOfWork and the database will drive out of sync. They can
  368. only be synchronized by calling ``EntityManager#flush()``. This section
  369. describes the effects of database and UnitOfWork being out of sync.
  370. - Entities that are scheduled for removal can still be queried from the database.
  371. They are returned from DQL and Repository queries and are visible in collections.
  372. - Entities that are passed to ``EntityManager#persist`` do not turn up in query
  373. results.
  374. - Entities that have changed will not be overwritten with the state from the database.
  375. This is because the identity map will detect the construction of an already existing
  376. entity and assumes its the most up to date version.
  377. ``EntityManager#flush()`` is never called implicitly by Doctrine. You always have to trigger it manually.
  378. Synchronizing New and Managed Entities
  379. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  380. The flush operation applies to a managed entity with the following
  381. semantics:
  382. - The entity itself is synchronized to the database using a SQL
  383. UPDATE statement, only if at least one persistent field has
  384. changed.
  385. - No SQL updates are executed if the entity did not change.
  386. The flush operation applies to a new entity with the following
  387. semantics:
  388. - The entity itself is synchronized to the database using a SQL
  389. INSERT statement.
  390. For all (initialized) relationships of the new or managed entity
  391. the following semantics apply to each associated entity X:
  392. - If X is new and persist operations are configured to cascade on
  393. the relationship, X will be persisted.
  394. - If X is new and no persist operations are configured to cascade
  395. on the relationship, an exception will be thrown as this indicates
  396. a programming error.
  397. - If X is removed and persist operations are configured to cascade
  398. on the relationship, an exception will be thrown as this indicates
  399. a programming error (X would be re-persisted by the cascade).
  400. - If X is detached and persist operations are configured to
  401. cascade on the relationship, an exception will be thrown (This is
  402. semantically the same as passing X to persist()).
  403. Synchronizing Removed Entities
  404. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  405. The flush operation applies to a removed entity by deleting its
  406. persistent state from the database. No cascade options are relevant
  407. for removed entities on flush, the cascade remove option is already
  408. executed during ``EntityManager#remove($entity)``.
  409. The size of a Unit of Work
  410. ~~~~~~~~~~~~~~~~~~~~~~~~~~
  411. The size of a Unit of Work mainly refers to the number of managed
  412. entities at a particular point in time.
  413. The cost of flushing
  414. ~~~~~~~~~~~~~~~~~~~~
  415. How costly a flush operation is, mainly depends on two factors:
  416. - The size of the EntityManager's current UnitOfWork.
  417. - The configured change tracking policies
  418. You can get the size of a UnitOfWork as follows:
  419. .. code-block:: php
  420. <?php
  421. $uowSize = $em->getUnitOfWork()->size();
  422. The size represents the number of managed entities in the Unit of
  423. Work. This size affects the performance of flush() operations due
  424. to change tracking (see "Change Tracking Policies") and, of course,
  425. memory consumption, so you may want to check it from time to time
  426. during development.
  427. .. note::
  428. Do not invoke ``flush`` after every change to an entity
  429. or every single invocation of persist/remove/merge/... This is an
  430. anti-pattern and unnecessarily reduces the performance of your
  431. application. Instead, form units of work that operate on your
  432. objects and call ``flush`` when you are done. While serving a
  433. single HTTP request there should be usually no need for invoking
  434. ``flush`` more than 0-2 times.
  435. Direct access to a Unit of Work
  436. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  437. You can get direct access to the Unit of Work by calling
  438. ``EntityManager#getUnitOfWork()``. This will return the UnitOfWork
  439. instance the EntityManager is currently using.
  440. .. code-block:: php
  441. <?php
  442. $uow = $em->getUnitOfWork();
  443. .. note::
  444. Directly manipulating a UnitOfWork is not recommended.
  445. When working directly with the UnitOfWork API, respect methods
  446. marked as INTERNAL by not using them and carefully read the API
  447. documentation.
  448. Entity State
  449. ~~~~~~~~~~~~
  450. As outlined in the architecture overview an entity can be in one of
  451. four possible states: NEW, MANAGED, REMOVED, DETACHED. If you
  452. explicitly need to find out what the current state of an entity is
  453. in the context of a certain ``EntityManager`` you can ask the
  454. underlying ``UnitOfWork``:
  455. .. code-block:: php
  456. <?php
  457. switch ($em->getUnitOfWork()->getEntityState($entity)) {
  458. case UnitOfWork::STATE_MANAGED:
  459. ...
  460. case UnitOfWork::STATE_REMOVED:
  461. ...
  462. case UnitOfWork::STATE_DETACHED:
  463. ...
  464. case UnitOfWork::STATE_NEW:
  465. ...
  466. }
  467. An entity is in MANAGED state if it is associated with an
  468. ``EntityManager`` and it is not REMOVED.
  469. An entity is in REMOVED state after it has been passed to
  470. ``EntityManager#remove()`` until the next flush operation of the
  471. same EntityManager. A REMOVED entity is still associated with an
  472. ``EntityManager`` until the next flush operation.
  473. An entity is in DETACHED state if it has persistent state and
  474. identity but is currently not associated with an
  475. ``EntityManager``.
  476. An entity is in NEW state if has no persistent state and identity
  477. and is not associated with an ``EntityManager`` (for example those
  478. just created via the "new" operator).
  479. Querying
  480. --------
  481. Doctrine 2 provides the following ways, in increasing level of
  482. power and flexibility, to query for persistent objects. You should
  483. always start with the simplest one that suits your needs.
  484. By Primary Key
  485. ~~~~~~~~~~~~~~
  486. The most basic way to query for a persistent object is by its
  487. identifier / primary key using the
  488. ``EntityManager#find($entityName, $id)`` method. Here is an
  489. example:
  490. .. code-block:: php
  491. <?php
  492. // $em instanceof EntityManager
  493. $user = $em->find('MyProject\Domain\User', $id);
  494. The return value is either the found entity instance or null if no
  495. instance could be found with the given identifier.
  496. Essentially, ``EntityManager#find()`` is just a shortcut for the
  497. following:
  498. .. code-block:: php
  499. <?php
  500. // $em instanceof EntityManager
  501. $user = $em->getRepository('MyProject\Domain\User')->find($id);
  502. ``EntityManager#getRepository($entityName)`` returns a repository
  503. object which provides many ways to retrieve entities of the
  504. specified type. By default, the repository instance is of type
  505. ``Doctrine\ORM\EntityRepository``. You can also use custom
  506. repository classes as shown later.
  507. By Simple Conditions
  508. ~~~~~~~~~~~~~~~~~~~~
  509. To query for one or more entities based on several conditions that
  510. form a logical conjunction, use the ``findBy`` and ``findOneBy``
  511. methods on a repository as follows:
  512. .. code-block:: php
  513. <?php
  514. // $em instanceof EntityManager
  515. // All users that are 20 years old
  516. $users = $em->getRepository('MyProject\Domain\User')->findBy(array('age' => 20));
  517. // All users that are 20 years old and have a surname of 'Miller'
  518. $users = $em->getRepository('MyProject\Domain\User')->findBy(array('age' => 20, 'surname' => 'Miller'));
  519. // A single user by its nickname
  520. $user = $em->getRepository('MyProject\Domain\User')->findOneBy(array('nickname' => 'romanb'));
  521. You can also load by owning side associations through the repository:
  522. .. code-block:: php
  523. <?php
  524. $number = $em->find('MyProject\Domain\Phonenumber', 1234);
  525. $user = $em->getRepository('MyProject\Domain\User')->findOneBy(array('phone' => $number->getId()));
  526. Be careful that this only works by passing the ID of the associated entity, not yet by passing the associated entity itself.
  527. The ``EntityRepository#findBy()`` method additionally accepts orderings, limit and offset as second to fourth parameters:
  528. .. code-block:: php
  529. <?php
  530. $tenUsers = $em->getRepository('MyProject\Domain\User')->findBy(array('age' => 20), array('name' => 'ASC'), 10, 0);
  531. If you pass an array of values Doctrine will convert the query into a WHERE field IN (..) query automatically:
  532. .. code-block:: php
  533. <?php
  534. $users = $em->getRepository('MyProject\Domain\User')->findBy(array('age' => array(20, 30, 40)));
  535. // translates roughly to: SELECT * FROM users WHERE age IN (20, 30, 40)
  536. An EntityRepository also provides a mechanism for more concise
  537. calls through its use of ``__call``. Thus, the following two
  538. examples are equivalent:
  539. .. code-block:: php
  540. <?php
  541. // A single user by its nickname
  542. $user = $em->getRepository('MyProject\Domain\User')->findOneBy(array('nickname' => 'romanb'));
  543. // A single user by its nickname (__call magic)
  544. $user = $em->getRepository('MyProject\Domain\User')->findOneByNickname('romanb');
  545. By Criteria
  546. ~~~~~~~~~~~
  547. .. versionadded:: 2.3
  548. The Repository implement the ``Doctrine\Common\Collections\Selectable``
  549. interface. That means you can build ``Doctrine\Common\Collections\Criteria``
  550. and pass them to the ``matching($criteria)`` method.
  551. See the :ref:`Working with Associations: Filtering collections
  552. <filtering-collections>`.
  553. By Eager Loading
  554. ~~~~~~~~~~~~~~~~
  555. Whenever you query for an entity that has persistent associations
  556. and these associations are mapped as EAGER, they will automatically
  557. be loaded together with the entity being queried and is thus
  558. immediately available to your application.
  559. By Lazy Loading
  560. ~~~~~~~~~~~~~~~
  561. Whenever you have a managed entity instance at hand, you can
  562. traverse and use any associations of that entity that are
  563. configured LAZY as if they were in-memory already. Doctrine will
  564. automatically load the associated objects on demand through the
  565. concept of lazy-loading.
  566. By DQL
  567. ~~~~~~
  568. The most powerful and flexible method to query for persistent
  569. objects is the Doctrine Query Language, an object query language.
  570. DQL enables you to query for persistent objects in the language of
  571. objects. DQL understands classes, fields, inheritance and
  572. associations. DQL is syntactically very similar to the familiar SQL
  573. but *it is not SQL*.
  574. A DQL query is represented by an instance of the
  575. ``Doctrine\ORM\Query`` class. You create a query using
  576. ``EntityManager#createQuery($dql)``. Here is a simple example:
  577. .. code-block:: php
  578. <?php
  579. // $em instanceof EntityManager
  580. // All users with an age between 20 and 30 (inclusive).
  581. $q = $em->createQuery("select u from MyDomain\Model\User u where u.age >= 20 and u.age <= 30");
  582. $users = $q->getResult();
  583. Note that this query contains no knowledge about the relational
  584. schema, only about the object model. DQL supports positional as
  585. well as named parameters, many functions, (fetch) joins,
  586. aggregates, subqueries and much more. Detailed information about
  587. DQL and its syntax as well as the Doctrine class can be found in
  588. :doc:`the dedicated chapter <dql-doctrine-query-language>`.
  589. For programmatically building up queries based on conditions that
  590. are only known at runtime, Doctrine provides the special
  591. ``Doctrine\ORM\QueryBuilder`` class. More information on
  592. constructing queries with a QueryBuilder can be found
  593. :doc:`in Query Builder chapter <query-builder>`.
  594. By Native Queries
  595. ~~~~~~~~~~~~~~~~~
  596. As an alternative to DQL or as a fallback for special SQL
  597. statements native queries can be used. Native queries are built by
  598. using a hand-crafted SQL query and a ResultSetMapping that
  599. describes how the SQL result set should be transformed by Doctrine.
  600. More information about native queries can be found in
  601. :doc:`the dedicated chapter <native-sql>`.
  602. Custom Repositories
  603. ~~~~~~~~~~~~~~~~~~~
  604. By default the EntityManager returns a default implementation of
  605. ``Doctrine\ORM\EntityRepository`` when you call
  606. ``EntityManager#getRepository($entityClass)``. You can overwrite
  607. this behaviour by specifying the class name of your own Entity
  608. Repository in the Annotation, XML or YAML metadata. In large
  609. applications that require lots of specialized DQL queries using a
  610. custom repository is one recommended way of grouping these queries
  611. in a central location.
  612. .. code-block:: php
  613. <?php
  614. namespace MyDomain\Model;
  615. use Doctrine\ORM\EntityRepository;
  616. /**
  617. * @entity(repositoryClass="MyDomain\Model\UserRepository")
  618. */
  619. class User
  620. {
  621. }
  622. class UserRepository extends EntityRepository
  623. {
  624. public function getAllAdminUsers()
  625. {
  626. return $this->_em->createQuery('SELECT u FROM MyDomain\Model\User u WHERE u.status = "admin"')
  627. ->getResult();
  628. }
  629. }
  630. You can access your repository now by calling:
  631. .. code-block:: php
  632. <?php
  633. // $em instanceof EntityManager
  634. $admins = $em->getRepository('MyDomain\Model\User')->getAllAdminUsers();