mongodb-odm-docs-dash/build.docset/Contents/Resources/Documents/reference/working-with-objects.html

653 lines
43 KiB
HTML
Raw Normal View History

2017-12-02 03:35:11 +00:00
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Working with Objects &mdash; Doctrine MongoDB ODM 1.1.5 documentation</title>
<link rel="stylesheet" href="../_static/bootstrap/css/bootstrap.min.css" type="text/css" />
<link rel="stylesheet" href="../_static/default.css" type="text/css" />
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="../_static/layout.css" type="text/css" />
<link rel="stylesheet" href="../_static/configurationblock.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '../',
VERSION: '1.1.5',
COLLAPSE_MODINDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="../_static/jquery.js"></script>
<script type="text/javascript" src="../_static/configurationblock.js"></script>
<script type="text/javascript" src="../_static/underscore.js"></script>
<script type="text/javascript" src="../_static/configurationblock.js"></script>
<script type="text/javascript" src="../_static/doctools.js"></script>
<script type="text/javascript" src="../_static/configurationblock.js"></script>
<script src="../_static/bootstrap/js/bootstrap.min.js"></script>
<script type="text/javascript">
<!--
$(document).ready(function() {
$("#versions").change(function() {
var docsUrl = $(this).val();
window.location.href = docsUrl;
});
});
-->
</script>
<link rel="shortcut icon" href="../_static/doctrine.ico"/>
<link rel="search" title="Search" href="../search.html" />
<link rel="top" title="Doctrine MongoDB ODM 1.1.5 documentation" href="../index.html" />
</head>
<body>
<div id="wrapper">
<div id="header">
<h1 id="h1title"></h1>
<div id="logo">
<a href="http://www.doctrine-project.org/">Doctrine - PHP Database Libraries</a>
</div>
</div>
<div id="nav" class="cls">
<div class="tl cls">
<ul>
<li><a target="_top" href="http://www.doctrine-project.org/">Home</a></li>
<li><a target="_top" href="http://www.doctrine-project.org/about.html">About</a></li>
<li><a target="_top" href="http://www.doctrine-project.org/projects.html">Projects</a></li>
<li><a target="_top" href="http://www.doctrine-project.org/contribute.html">Contribute</a></li>
<li><a target="_top" href="http://www.doctrine-project.org/community.html">Community</a></li>
<li><a target="_top" href="http://www.doctrine-project.org/archive.html">Blog</a></li>
<li><a target="_top" href="http://www.doctrine-project.org/jira">Development</a></li>
</ul>
</div>
</div>
<div id="content" class="cls">
<div class="related">
<h3>Navigation</h3>
<ul>
<li><a href="/">Doctrine Homepage</a> &raquo;</li>
<li><a href="../index.html">Doctrine MongoDB ODM 1.1.5 documentation</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" >
<div class="section" id="working-with-objects">
<h1>Working with Objects<a class="headerlink" href="#working-with-objects" title="Permalink to this headline"></a></h1>
<div class="section" id="understanding">
<h2>Understanding<a class="headerlink" href="#understanding" title="Permalink to this headline"></a></h2>
<p>In this chapter we will help you understand the <code class="docutils literal"><span class="pre">DocumentManager</span></code>
and the <code class="docutils literal"><span class="pre">UnitOfWork</span></code>. A Unit of Work is similar to an
object-level transaction. A new Unit of Work is implicitly started
when a DocumentManager is initially created or after
<code class="docutils literal"><span class="pre">DocumentManager#flush()</span></code> has been invoked. A Unit of Work is
committed (and a new one started) by invoking
<code class="docutils literal"><span class="pre">DocumentManager#flush()</span></code>.</p>
<p>A Unit of Work can be manually closed by calling
<code class="docutils literal"><span class="pre">DocumentManager#close()</span></code>. Any changes to objects within this
Unit of Work that have not yet been persisted are lost.</p>
<div class="section" id="the-size-of-a-unit-of-work">
<h3>The size of a Unit of Work<a class="headerlink" href="#the-size-of-a-unit-of-work" title="Permalink to this headline"></a></h3>
<p>The size of a Unit of Work mainly refers to the number of managed
documents at a particular point in time.</p>
</div>
<div class="section" id="the-cost-of-flush">
<h3>The cost of flush()<a class="headerlink" href="#the-cost-of-flush" title="Permalink to this headline"></a></h3>
<p>How costly a flush operation is in terms of performance mainly
depends on the size. You can get the size of your Unit of Work as
follows:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nv">$uowSize</span> <span class="o">=</span> <span class="nv">$dm</span><span class="o">-&gt;</span><span class="na">getUnitOfWork</span><span class="p">()</span><span class="o">-&gt;</span><span class="na">size</span><span class="p">();</span>
</pre></div>
</div>
<p>The size represents the number of managed documents in the Unit of
Work. This size affects the performance of flush() operations due
to change tracking and, of course, memory consumption, so you may
want to check it from time to time during development.</p>
<div class="admonition caution">
<p class="first admonition-title">Caution</p>
<p class="last">Do not invoke <code class="docutils literal"><span class="pre">flush</span></code> after every change to a
document or every single invocation of persist/remove/merge/...
This is an anti-pattern and unnecessarily reduces the performance
of your application. Instead, form units of work that operate on
your objects and call <code class="docutils literal"><span class="pre">flush</span></code> when you are done. While serving a
single HTTP request there should be usually no need for invoking
<code class="docutils literal"><span class="pre">flush</span></code> more than 0-2 times.</p>
</div>
</div>
<div class="section" id="direct-access-to-a-unit-of-work">
<h3>Direct access to a Unit of Work<a class="headerlink" href="#direct-access-to-a-unit-of-work" title="Permalink to this headline"></a></h3>
<p>You can get direct access to the Unit of Work by calling
<code class="docutils literal"><span class="pre">DocumentManager#getUnitOfWork()</span></code>. This will return the
UnitOfWork instance the DocumentManager is currently using.</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nv">$uow</span> <span class="o">=</span> <span class="nv">$dm</span><span class="o">-&gt;</span><span class="na">getUnitOfWork</span><span class="p">();</span>
</pre></div>
</div>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">Directly manipulating a UnitOfWork is not recommended.
When working directly with the UnitOfWork API, respect methods
marked as INTERNAL by not using them and carefully read the API
documentation.</p>
</div>
</div>
</div>
<div class="section" id="persisting-documents">
<h2>Persisting documents<a class="headerlink" href="#persisting-documents" title="Permalink to this headline"></a></h2>
<p>A document can be made persistent by passing it to the
<code class="docutils literal"><span class="pre">DocumentManager#persist($document)</span></code> method. By applying the
persist operation on some document, that document becomes MANAGED,
which means that its persistence is from now on managed by an
DocumentManager. As a result the persistent state of such a
document will subsequently be properly synchronized with the
database when <code class="docutils literal"><span class="pre">DocumentManager#flush()</span></code> is invoked.</p>
<div class="admonition caution">
<p class="first admonition-title">Caution</p>
<p class="last">Invoking the <code class="docutils literal"><span class="pre">persist</span></code> method on a document does NOT
cause an immediate insert to be issued on the database. Doctrine
applies a strategy called &quot;transactional write-behind&quot;, which means
that it will delay most operations until
<code class="docutils literal"><span class="pre">DocumentManager#flush()</span></code> is invoked which will then issue all
necessary queries to synchronize your objects with the database in
the most efficient way.</p>
</div>
<p>Example:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nv">$user</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">User</span><span class="p">();</span>
<span class="nv">$user</span><span class="o">-&gt;</span><span class="na">setUsername</span><span class="p">(</span><span class="s1">&#39;jwage&#39;</span><span class="p">);</span>
<span class="nv">$user</span><span class="o">-&gt;</span><span class="na">setPassword</span><span class="p">(</span><span class="s1">&#39;changeme&#39;</span><span class="p">);</span>
<span class="nv">$dm</span><span class="o">-&gt;</span><span class="na">persist</span><span class="p">(</span><span class="nv">$user</span><span class="p">);</span>
<span class="nv">$dm</span><span class="o">-&gt;</span><span class="na">flush</span><span class="p">();</span>
</pre></div>
</div>
<div class="admonition caution">
<p class="first admonition-title">Caution</p>
<p class="last">The document identifier is generated during <code class="docutils literal"><span class="pre">persist</span></code> if not previously
specified. Users cannot rely on a document identifier being available during
the <code class="docutils literal"><span class="pre">prePersist</span></code> event.</p>
</div>
<p>The semantics of the persist operation, applied on a document X,
are as follows:</p>
<ul class="simple">
<li>If X is a new document, it becomes managed. The document X will be
entered into the database as a result of the flush operation.</li>
<li>If X is a preexisting managed document, it is ignored by the
persist operation. However, the persist operation is cascaded to
documents referenced by X, if the relationships from X to these
other documents are mapped with cascade=PERSIST or cascade=ALL.</li>
<li>If X is a removed document, it becomes managed.</li>
<li>If X is a detached document, the behavior is undefined.</li>
</ul>
<div class="admonition caution">
<p class="first admonition-title">Caution</p>
<p class="last">Do not pass detached documents to the persist operation.</p>
</div>
</div>
<div class="section" id="flush-options">
<span id="id1"></span><h2>Flush Options<a class="headerlink" href="#flush-options" title="Permalink to this headline"></a></h2>
<p>When committing your documents you can specify an array of options to the
<code class="docutils literal"><span class="pre">flush</span></code> method. With it you can send options to the underlying database
like <code class="docutils literal"><span class="pre">safe</span></code>, <code class="docutils literal"><span class="pre">fsync</span></code>, etc.</p>
<p>Example:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nv">$user</span> <span class="o">=</span> <span class="nv">$dm</span><span class="o">-&gt;</span><span class="na">getRepository</span><span class="p">(</span><span class="s1">&#39;User&#39;</span><span class="p">)</span><span class="o">-&gt;</span><span class="na">find</span><span class="p">(</span><span class="nv">$userId</span><span class="p">);</span>
<span class="c1">// ...</span>
<span class="nv">$user</span><span class="o">-&gt;</span><span class="na">setPassword</span><span class="p">(</span><span class="s1">&#39;changeme&#39;</span><span class="p">);</span>
<span class="nv">$dm</span><span class="o">-&gt;</span><span class="na">flush</span><span class="p">(</span><span class="k">null</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">&#39;safe&#39;</span> <span class="o">=&gt;</span> <span class="k">true</span><span class="p">,</span> <span class="s1">&#39;fsync&#39;</span> <span class="o">=&gt;</span> <span class="k">true</span><span class="p">));</span>
</pre></div>
</div>
<p>You can configure the default flush options on your <code class="docutils literal"><span class="pre">Configuration</span></code> object
if you want to set them globally for all flushes.</p>
<p>Example:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nv">$config</span><span class="o">-&gt;</span><span class="na">setDefaultCommitOptions</span><span class="p">(</span><span class="k">array</span><span class="p">(</span>
<span class="s1">&#39;safe&#39;</span> <span class="o">=&gt;</span> <span class="k">true</span><span class="p">,</span>
<span class="s1">&#39;fsync&#39;</span> <span class="o">=&gt;</span> <span class="k">true</span>
<span class="p">));</span>
</pre></div>
</div>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">Safe is set to true by default for all writes when using the ODM.</p>
</div>
</div>
<div class="section" id="removing-documents">
<h2>Removing documents<a class="headerlink" href="#removing-documents" title="Permalink to this headline"></a></h2>
<p>A document can be removed from persistent storage by passing it to
the <code class="docutils literal"><span class="pre">DocumentManager#remove($document)</span></code> method. By applying the
<code class="docutils literal"><span class="pre">remove</span></code> operation on some document, that document becomes
REMOVED, which means that its persistent state will be deleted once
<code class="docutils literal"><span class="pre">DocumentManager#flush()</span></code> is invoked. The in-memory state of a
document is unaffected by the <code class="docutils literal"><span class="pre">remove</span></code> operation.</p>
<div class="admonition caution">
<p class="first admonition-title">Caution</p>
<p class="last">Just like <code class="docutils literal"><span class="pre">persist</span></code>, invoking <code class="docutils literal"><span class="pre">remove</span></code> on a
document does NOT cause an immediate query to be issued on the
database. The document will be removed on the next invocation of
<code class="docutils literal"><span class="pre">DocumentManager#flush()</span></code> that involves that document.</p>
</div>
<p>Example:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nv">$dm</span><span class="o">-&gt;</span><span class="na">remove</span><span class="p">(</span><span class="nv">$user</span><span class="p">);</span>
<span class="nv">$dm</span><span class="o">-&gt;</span><span class="na">flush</span><span class="p">();</span>
</pre></div>
</div>
<p>The semantics of the remove operation, applied to a document X are
as follows:</p>
<ul class="simple">
<li>If X is a new document, it is ignored by the remove operation.
However, the remove operation is cascaded to documents referenced
by X, if the relationship from X to these other documents is mapped
with cascade=REMOVE or cascade=ALL.</li>
<li>If X is a managed document, the remove operation causes it to
become removed. The remove operation is cascaded to documents
referenced by X, if the relationships from X to these other
documents is mapped with cascade=REMOVE or cascade=ALL.</li>
<li>If X is a detached document, an InvalidArgumentException will be
thrown.</li>
<li>If X is a removed document, it is ignored by the remove operation.</li>
<li>A removed document X will be removed from the database as a result
of the flush operation.</li>
</ul>
</div>
<div class="section" id="detaching-documents">
<h2>Detaching documents<a class="headerlink" href="#detaching-documents" title="Permalink to this headline"></a></h2>
<p>A document is detached from a DocumentManager and thus no longer
managed by invoking the <code class="docutils literal"><span class="pre">DocumentManager#detach($document)</span></code>
method on it or by cascading the detach operation to it. Changes
made to the detached document, if any (including removal of the
document), will not be synchronized to the database after the
document has been detached.</p>
<p>Doctrine will not hold on to any references to a detached
document.</p>
<p>Example:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nv">$dm</span><span class="o">-&gt;</span><span class="na">detach</span><span class="p">(</span><span class="nv">$document</span><span class="p">);</span>
</pre></div>
</div>
<p>The semantics of the detach operation, applied to a document X are
as follows:</p>
<ul class="simple">
<li>If X is a managed document, the detach operation causes it to
become detached. The detach operation is cascaded to documents
referenced by X, if the relationships from X to these other
documents is mapped with cascade=DETACH or cascade=ALL. Documents
which previously referenced X will continue to reference X.</li>
<li>If X is a new or detached document, it is ignored by the detach
operation.</li>
<li>If X is a removed document, the detach operation is cascaded to
documents referenced by X, if the relationships from X to these
other documents is mapped with cascade=DETACH or
cascade=ALL/Documents which previously referenced X will continue
to reference X.</li>
</ul>
<p>There are several situations in which a document is detached
automatically without invoking the <code class="docutils literal"><span class="pre">detach</span></code> method:</p>
<ul class="simple">
<li>When <code class="docutils literal"><span class="pre">DocumentManager#clear()</span></code> is invoked, all documents that are
currently managed by the DocumentManager instance become detached.</li>
<li>When serializing a document. The document retrieved upon subsequent
unserialization will be detached (This is the case for all
documents that are serialized and stored in some cache).</li>
</ul>
<p>The <code class="docutils literal"><span class="pre">detach</span></code> operation is usually not as frequently needed and
used as <code class="docutils literal"><span class="pre">persist</span></code> and <code class="docutils literal"><span class="pre">remove</span></code>.</p>
</div>
<div class="section" id="merging-documents">
<h2>Merging documents<a class="headerlink" href="#merging-documents" title="Permalink to this headline"></a></h2>
<p>Merging documents refers to the merging of (usually detached)
documents into the context of a DocumentManager so that they
become managed again. To merge the state of a document into an
DocumentManager use the <code class="docutils literal"><span class="pre">DocumentManager#merge($document)</span></code>
method. The state of the passed document will be merged into a
managed copy of this document and this copy will subsequently be
returned.</p>
<p>Example:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nv">$detachedDocument</span> <span class="o">=</span> <span class="nb">unserialize</span><span class="p">(</span><span class="nv">$serializedDocument</span><span class="p">);</span> <span class="c1">// some detached document</span>
<span class="nv">$document</span> <span class="o">=</span> <span class="nv">$dm</span><span class="o">-&gt;</span><span class="na">merge</span><span class="p">(</span><span class="nv">$detachedDocument</span><span class="p">);</span>
<span class="c1">// $document now refers to the fully managed copy returned by the merge operation.</span>
<span class="c1">// The DocumentManager $dm now manages the persistence of $document as usual.</span>
<span class="nx">The</span> <span class="nx">semantics</span> <span class="nx">of</span> <span class="nx">the</span> <span class="nx">merge</span> <span class="nx">operation</span><span class="p">,</span> <span class="nx">applied</span> <span class="nx">to</span> <span class="nx">a</span> <span class="nx">document</span> <span class="nx">X</span><span class="p">,</span> <span class="nx">are</span>
<span class="k">as</span> <span class="nx">follows</span><span class="o">:</span>
</pre></div>
</div>
<ul class="simple">
<li>If X is a detached document, the state of X is copied onto a
pre-existing managed document instance X' of the same iddocument or
a new managed copy X' of X is created.</li>
<li>If X is a new document instance, an InvalidArgumentException will
be thrown.</li>
<li>If X is a removed document instance, an InvalidArgumentException
will be thrown.</li>
<li>If X is a managed document, it is ignored by the merge operation,
however, the merge operation is cascaded to documents referenced by
relationships from X if these relationships have been mapped with
the cascade element value MERGE or ALL.</li>
<li>For all documents Y referenced by relationships from X having the
cascade element value MERGE or ALL, Y is merged recursively as Y'.
For all such Y referenced by X, X' is set to reference Y'. (Note
that if X is managed then X is the same object as X'.)</li>
<li>If X is a document merged to X', with a reference to another
document Y, where cascade=MERGE or cascade=ALL is not specified,
then navigation of the same association from X' yields a reference
to a managed object Y' with the same persistent iddocument as Y.</li>
</ul>
<p>The <code class="docutils literal"><span class="pre">merge</span></code> operation is usually not as frequently needed and
used as <code class="docutils literal"><span class="pre">persist</span></code> and <code class="docutils literal"><span class="pre">remove</span></code>. The most common scenario for
the <code class="docutils literal"><span class="pre">merge</span></code> operation is to reattach documents to an
DocumentManager that come from some cache (and are therefore
detached) and you want to modify and persist such a document.</p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">If you load some detached documents from a cache and you
do not need to persist or delete them or otherwise make use of them
without the need for persistence services there is no need to use
<code class="docutils literal"><span class="pre">merge</span></code>. I.e. you can simply pass detached objects from a cache
directly to the view.</p>
</div>
</div>
<div class="section" id="references">
<h2>References<a class="headerlink" href="#references" title="Permalink to this headline"></a></h2>
<p>References between documents and embedded documents are represented
just like in regular object-oriented PHP, with references to other
objects or collections of objects.</p>
</div>
<div class="section" id="establishing-references">
<h2>Establishing References<a class="headerlink" href="#establishing-references" title="Permalink to this headline"></a></h2>
<p>Establishing a reference to another document is straight forward:</p>
<p>Here is an example where we add a new comment to an article:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nv">$comment</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Comment</span><span class="p">();</span>
<span class="c1">// ...</span>
<span class="nv">$article</span><span class="o">-&gt;</span><span class="na">getComments</span><span class="p">()</span><span class="o">-&gt;</span><span class="na">add</span><span class="p">(</span><span class="nv">$comment</span><span class="p">);</span>
</pre></div>
</div>
<p>Or you can set a single reference:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nv">$address</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Address</span><span class="p">();</span>
<span class="c1">// ...</span>
<span class="nv">$user</span><span class="o">-&gt;</span><span class="na">setAddress</span><span class="p">(</span><span class="nv">$address</span><span class="p">);</span>
</pre></div>
</div>
</div>
<div class="section" id="removing-references">
<h2>Removing References<a class="headerlink" href="#removing-references" title="Permalink to this headline"></a></h2>
<p>Removing an association between two documents is similarly
straight-forward. There are two strategies to do so, by key and by
element. Here are some examples:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nv">$article</span><span class="o">-&gt;</span><span class="na">getComments</span><span class="p">()</span><span class="o">-&gt;</span><span class="na">removeElement</span><span class="p">(</span><span class="nv">$comment</span><span class="p">);</span>
<span class="nv">$article</span><span class="o">-&gt;</span><span class="na">getComments</span><span class="p">()</span><span class="o">-&gt;</span><span class="na">remove</span><span class="p">(</span><span class="nv">$ithComment</span><span class="p">);</span>
</pre></div>
</div>
<p>Or you can remove a single reference:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nv">$user</span><span class="o">-&gt;</span><span class="na">setAddress</span><span class="p">(</span><span class="k">null</span><span class="p">);</span>
</pre></div>
</div>
<p>When working with collections, keep in mind that a Collection is
essentially an ordered map (just like a PHP array). That is why the
<code class="docutils literal"><span class="pre">remove</span></code> operation accepts an index/key. <code class="docutils literal"><span class="pre">removeElement</span></code> is a
separate method that has O(n) complexity, where n is the size of
the map.</p>
</div>
<div class="section" id="transitive-persistence">
<h2>Transitive persistence<a class="headerlink" href="#transitive-persistence" title="Permalink to this headline"></a></h2>
<p>Persisting, removing, detaching and merging individual documents
can become pretty cumbersome, especially when a larger object graph
with collections is involved. Therefore Doctrine provides a
mechanism for transitive persistence through cascading of these
operations. Each reference to another document or a collection of
documents can be configured to automatically cascade certain
operations. By default, no operations are cascaded.</p>
<p>The following cascade options exist:</p>
<ul class="simple">
<li>persist : Cascades persist operations to the associated documents.</li>
<li>remove : Cascades remove operations to the associated documents.</li>
<li>merge : Cascades merge operations to the associated documents.</li>
<li>detach : Cascades detach operations to the associated documents.</li>
<li>all : Cascades persist, remove, merge and detach operations to
associated documents.</li>
</ul>
<p>The following example shows an association to a number of
addresses. If persist() or remove() is invoked on any User
document, it will be cascaded to all associated Address documents
in the $addresses collection.</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="k">class</span> <span class="nc">User</span>
<span class="p">{</span>
<span class="c1">//...</span>
<span class="sd">/**</span>
<span class="sd"> * @ReferenceMany(targetDocument=&quot;Address&quot;, cascade={&quot;persist&quot;, &quot;remove&quot;})</span>
<span class="sd"> */</span>
<span class="k">private</span> <span class="nv">$addresses</span><span class="p">;</span>
<span class="c1">//...</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Even though automatic cascading is convenient it should be used
with care. Do not blindly apply cascade=all to all associations as
it will unnecessarily degrade the performance of your application.</p>
</div>
<div class="section" id="querying">
<h2>Querying<a class="headerlink" href="#querying" title="Permalink to this headline"></a></h2>
<p>Doctrine provides the following ways, in increasing level of power
and flexibility, to query for persistent objects. You should always
start with the simplest one that suits your needs.</p>
<div class="section" id="by-primary-key">
<h3>By Primary Key<a class="headerlink" href="#by-primary-key" title="Permalink to this headline"></a></h3>
<p>The most basic way to query for a persistent object is by its
identifier / primary key using the
<code class="docutils literal"><span class="pre">DocumentManager#find($documentName,</span> <span class="pre">$id)</span></code> method. Here is an
example:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nv">$user</span> <span class="o">=</span> <span class="nv">$dm</span><span class="o">-&gt;</span><span class="na">find</span><span class="p">(</span><span class="s1">&#39;User&#39;</span><span class="p">,</span> <span class="nv">$id</span><span class="p">);</span>
</pre></div>
</div>
<p>The return value is either the found document instance or null if
no instance could be found with the given identifier.</p>
<p>Essentially, <code class="docutils literal"><span class="pre">DocumentManager#find()</span></code> is just a shortcut for the
following:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nv">$user</span> <span class="o">=</span> <span class="nv">$dm</span><span class="o">-&gt;</span><span class="na">getRepository</span><span class="p">(</span><span class="s1">&#39;User&#39;</span><span class="p">)</span><span class="o">-&gt;</span><span class="na">find</span><span class="p">(</span><span class="nv">$id</span><span class="p">);</span>
</pre></div>
</div>
<p><code class="docutils literal"><span class="pre">DocumentManager#getRepository($documentName)</span></code> returns a
repository object which provides many ways to retrieve documents of
the specified type. By default, the repository instance is of type
<code class="docutils literal"><span class="pre">Doctrine\ODM\MongoDB\DocumentRepository</span></code>. You can also use
custom repository classes.</p>
</div>
<div class="section" id="by-simple-conditions">
<h3>By Simple Conditions<a class="headerlink" href="#by-simple-conditions" title="Permalink to this headline"></a></h3>
<p>To query for one or more documents based on several conditions that
form a logical conjunction, use the <code class="docutils literal"><span class="pre">findBy</span></code> and <code class="docutils literal"><span class="pre">findOneBy</span></code>
methods on a repository as follows:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="c1">// All users that are 20 years old</span>
<span class="nv">$users</span> <span class="o">=</span> <span class="nv">$dm</span><span class="o">-&gt;</span><span class="na">getRepository</span><span class="p">(</span><span class="s1">&#39;User&#39;</span><span class="p">)</span><span class="o">-&gt;</span><span class="na">findBy</span><span class="p">(</span><span class="k">array</span><span class="p">(</span><span class="s1">&#39;age&#39;</span> <span class="o">=&gt;</span> <span class="mi">20</span><span class="p">));</span>
<span class="c1">// All users that are 20 years old and have a surname of &#39;Miller&#39;</span>
<span class="nv">$users</span> <span class="o">=</span> <span class="nv">$dm</span><span class="o">-&gt;</span><span class="na">getRepository</span><span class="p">(</span><span class="s1">&#39;User&#39;</span><span class="p">)</span><span class="o">-&gt;</span><span class="na">findBy</span><span class="p">(</span><span class="k">array</span><span class="p">(</span><span class="s1">&#39;age&#39;</span> <span class="o">=&gt;</span> <span class="mi">20</span><span class="p">,</span> <span class="s1">&#39;surname&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;Miller&#39;</span><span class="p">));</span>
<span class="c1">// A single user by its nickname</span>
<span class="nv">$user</span> <span class="o">=</span> <span class="nv">$dm</span><span class="o">-&gt;</span><span class="na">getRepository</span><span class="p">(</span><span class="s1">&#39;User&#39;</span><span class="p">)</span><span class="o">-&gt;</span><span class="na">findOneBy</span><span class="p">(</span><span class="k">array</span><span class="p">(</span><span class="s1">&#39;nickname&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;romanb&#39;</span><span class="p">));</span>
</pre></div>
</div>
<p>A DocumentRepository also provides a mechanism for more concise
calls through its use of <code class="docutils literal"><span class="pre">__call</span></code>. Thus, the following two
examples are equivalent:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="c1">// A single user by its nickname</span>
<span class="nv">$user</span> <span class="o">=</span> <span class="nv">$dm</span><span class="o">-&gt;</span><span class="na">getRepository</span><span class="p">(</span><span class="s1">&#39;User&#39;</span><span class="p">)</span><span class="o">-&gt;</span><span class="na">findOneBy</span><span class="p">(</span><span class="k">array</span><span class="p">(</span><span class="s1">&#39;nickname&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;romanb&#39;</span><span class="p">));</span>
<span class="c1">// A single user by its nickname (__call magic)</span>
<span class="nv">$user</span> <span class="o">=</span> <span class="nv">$dm</span><span class="o">-&gt;</span><span class="na">getRepository</span><span class="p">(</span><span class="s1">&#39;User&#39;</span><span class="p">)</span><span class="o">-&gt;</span><span class="na">findOneByNickname</span><span class="p">(</span><span class="s1">&#39;romanb&#39;</span><span class="p">);</span>
</pre></div>
</div>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">You can learn more about Repositories in a <a class="reference internal" href="document-repositories.html#document-repositories"><span class="std std-ref">dedicated chapter</span></a>.</p>
</div>
</div>
<div class="section" id="by-lazy-loading">
<h3>By Lazy Loading<a class="headerlink" href="#by-lazy-loading" title="Permalink to this headline"></a></h3>
<p>Whenever you have a managed document instance at hand, you can
traverse and use any associations of that document as if they were
in-memory already. Doctrine will automatically load the associated
objects on demand through the concept of lazy-loading.</p>
</div>
<div class="section" id="by-query-builder-objects">
<h3>By Query Builder Objects<a class="headerlink" href="#by-query-builder-objects" title="Permalink to this headline"></a></h3>
<p>The most powerful and flexible method to query for persistent
objects is the QueryBuilder object. The QueryBuilder object enables you to query
for persistent objects with a fluent object oriented interface.</p>
<p>You can create a query using
<code class="docutils literal"><span class="pre">DocumentManager#createQueryBuilder($documentName</span> <span class="pre">=</span> <span class="pre">null)</span></code>. Here is a
simple example:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="c1">// All users with an age between 20 and 30 (inclusive).</span>
<span class="nv">$qb</span> <span class="o">=</span> <span class="nv">$dm</span><span class="o">-&gt;</span><span class="na">createQueryBuilder</span><span class="p">(</span><span class="s1">&#39;User&#39;</span><span class="p">)</span>
<span class="o">-&gt;</span><span class="na">field</span><span class="p">(</span><span class="s1">&#39;age&#39;</span><span class="p">)</span><span class="o">-&gt;</span><span class="na">range</span><span class="p">(</span><span class="mi">20</span><span class="p">,</span> <span class="mi">30</span><span class="p">);</span>
<span class="nv">$q</span> <span class="o">=</span> <span class="nv">$qb</span><span class="o">-&gt;</span><span class="na">getQuery</span><span class="p">()</span>
<span class="nv">$users</span> <span class="o">=</span> <span class="nv">$q</span><span class="o">-&gt;</span><span class="na">execute</span><span class="p">();</span>
</pre></div>
</div>
</div>
<div class="section" id="by-reference">
<h3>By Reference<a class="headerlink" href="#by-reference" title="Permalink to this headline"></a></h3>
<p>To query documents with a ReferenceOne association to another document, use the <code class="docutils literal"><span class="pre">references($document)</span></code> expression:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nv">$group</span> <span class="o">=</span> <span class="nv">$dm</span><span class="o">-&gt;</span><span class="na">find</span><span class="p">(</span><span class="s1">&#39;Group&#39;</span><span class="p">,</span> <span class="nv">$id</span><span class="p">);</span>
<span class="nv">$usersWithGroup</span> <span class="o">=</span> <span class="nv">$dm</span><span class="o">-&gt;</span><span class="na">createQueryBuilder</span><span class="p">(</span><span class="s1">&#39;User&#39;</span><span class="p">)</span>
<span class="o">-&gt;</span><span class="na">field</span><span class="p">(</span><span class="s1">&#39;group&#39;</span><span class="p">)</span><span class="o">-&gt;</span><span class="na">references</span><span class="p">(</span><span class="nv">$group</span><span class="p">)</span>
<span class="o">-&gt;</span><span class="na">getQuery</span><span class="p">()</span><span class="o">-&gt;</span><span class="na">execute</span><span class="p">();</span>
</pre></div>
</div>
<p>To find documents with a ReferenceMany association that includes a certain document, use the <code class="docutils literal"><span class="pre">includesReferenceTo($document)</span></code> expression:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nv">$users</span> <span class="o">=</span> <span class="nv">$dm</span><span class="o">-&gt;</span><span class="na">createQueryBuilder</span><span class="p">(</span><span class="s1">&#39;User&#39;</span><span class="p">)</span>
<span class="o">-&gt;</span><span class="na">field</span><span class="p">(</span><span class="s1">&#39;groups&#39;</span><span class="p">)</span><span class="o">-&gt;</span><span class="na">includesReferenceTo</span><span class="p">(</span><span class="nv">$group</span><span class="p">)</span>
<span class="o">-&gt;</span><span class="na">getQuery</span><span class="p">()</span><span class="o">-&gt;</span><span class="na">execute</span><span class="p">();</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<div id="searchbox" style="">
<h3>Search</h3>
<form class="search" action="http://readthedocs.org/search/project/" method="get">
<input type="text" name="q" size="18">
<input type="submit" value="Go">
<input type="hidden" name="selected_facets" value="project:">
</form>
</div>
<h3><a href="../index.html">Table Of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Working with Objects</a><ul>
<li><a class="reference internal" href="#understanding">Understanding</a><ul>
<li><a class="reference internal" href="#the-size-of-a-unit-of-work">The size of a Unit of Work</a></li>
<li><a class="reference internal" href="#the-cost-of-flush">The cost of flush()</a></li>
<li><a class="reference internal" href="#direct-access-to-a-unit-of-work">Direct access to a Unit of Work</a></li>
</ul>
</li>
<li><a class="reference internal" href="#persisting-documents">Persisting documents</a></li>
<li><a class="reference internal" href="#flush-options">Flush Options</a></li>
<li><a class="reference internal" href="#removing-documents">Removing documents</a></li>
<li><a class="reference internal" href="#detaching-documents">Detaching documents</a></li>
<li><a class="reference internal" href="#merging-documents">Merging documents</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#establishing-references">Establishing References</a></li>
<li><a class="reference internal" href="#removing-references">Removing References</a></li>
<li><a class="reference internal" href="#transitive-persistence">Transitive persistence</a></li>
<li><a class="reference internal" href="#querying">Querying</a><ul>
<li><a class="reference internal" href="#by-primary-key">By Primary Key</a></li>
<li><a class="reference internal" href="#by-simple-conditions">By Simple Conditions</a></li>
<li><a class="reference internal" href="#by-lazy-loading">By Lazy Loading</a></li>
<li><a class="reference internal" href="#by-query-builder-objects">By Query Builder Objects</a></li>
<li><a class="reference internal" href="#by-reference">By Reference</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="../_sources/reference/working-with-objects.rst.txt"
rel="nofollow">Show Source</a></li>
</ul>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="footer">
&copy; Copyright 2013, Doctrine Project Team.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.6.2.
<br/>
<a target="_BLANK" href="http://www.servergrove.com"><img src="http://www.doctrine-project.org/_static/servergrove.jpg" /></a> <br/><br/>
<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_s-xclick" />
<input type="hidden" name="hosted_button_id" value="BAE2E3XANQ77Y" />
<input type="image" src="https://www.paypal.com/en_US/i/btn/btn_donateCC_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!" />
<img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1" />
</form>
</div>
</div>
<div id="bot-rcnr">
<div class="tl"><!-- corner --></div>
</div>
</div>
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-288343-7";
urchinTracker();
</script>
<a class="githublink" href="http://github.com/doctrine"><img src="https://s3.amazonaws.com/github/ribbons/forkme_right_orange_ff7600.png" alt="Fork me on GitHub"></a>
</body>
</html>