653 lines
43 KiB
HTML
653 lines
43 KiB
HTML
|
<!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 — 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> »</li>
|
||
|
<li><a href="../index.html">Doctrine MongoDB ODM 1.1.5 documentation</a> »</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"><?php</span>
|
||
|
|
||
|
<span class="nv">$uowSize</span> <span class="o">=</span> <span class="nv">$dm</span><span class="o">-></span><span class="na">getUnitOfWork</span><span class="p">()</span><span class="o">-></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"><?php</span>
|
||
|
|
||
|
<span class="nv">$uow</span> <span class="o">=</span> <span class="nv">$dm</span><span class="o">-></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 "transactional write-behind", 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"><?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">-></span><span class="na">setUsername</span><span class="p">(</span><span class="s1">'jwage'</span><span class="p">);</span>
|
||
|
<span class="nv">$user</span><span class="o">-></span><span class="na">setPassword</span><span class="p">(</span><span class="s1">'changeme'</span><span class="p">);</span>
|
||
|
<span class="nv">$dm</span><span class="o">-></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">-></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"><?php</span>
|
||
|
|
||
|
<span class="nv">$user</span> <span class="o">=</span> <span class="nv">$dm</span><span class="o">-></span><span class="na">getRepository</span><span class="p">(</span><span class="s1">'User'</span><span class="p">)</span><span class="o">-></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">-></span><span class="na">setPassword</span><span class="p">(</span><span class="s1">'changeme'</span><span class="p">);</span>
|
||
|
<span class="nv">$dm</span><span class="o">-></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">'safe'</span> <span class="o">=></span> <span class="k">true</span><span class="p">,</span> <span class="s1">'fsync'</span> <span class="o">=></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"><?php</span>
|
||
|
|
||
|
<span class="nv">$config</span><span class="o">-></span><span class="na">setDefaultCommitOptions</span><span class="p">(</span><span class="k">array</span><span class="p">(</span>
|
||
|
<span class="s1">'safe'</span> <span class="o">=></span> <span class="k">true</span><span class="p">,</span>
|
||
|
<span class="s1">'fsync'</span> <span class="o">=></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"><?php</span>
|
||
|
|
||
|
<span class="nv">$dm</span><span class="o">-></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">-></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"><?php</span>
|
||
|
|
||
|
<span class="nv">$dm</span><span class="o">-></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"><?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">-></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"><?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">-></span><span class="na">getComments</span><span class="p">()</span><span class="o">-></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"><?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">-></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"><?php</span>
|
||
|
|
||
|
<span class="nv">$article</span><span class="o">-></span><span class="na">getComments</span><span class="p">()</span><span class="o">-></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">-></span><span class="na">getComments</span><span class="p">()</span><span class="o">-></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"><?php</span>
|
||
|
|
||
|
<span class="nv">$user</span><span class="o">-></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"><?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="Address", cascade={"persist", "remove"})</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"><?php</span>
|
||
|
|
||
|
<span class="nv">$user</span> <span class="o">=</span> <span class="nv">$dm</span><span class="o">-></span><span class="na">find</span><span class="p">(</span><span class="s1">'User'</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"><?php</span>
|
||
|
|
||
|
<span class="nv">$user</span> <span class="o">=</span> <span class="nv">$dm</span><span class="o">-></span><span class="na">getRepository</span><span class="p">(</span><span class="s1">'User'</span><span class="p">)</span><span class="o">-></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"><?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">-></span><span class="na">getRepository</span><span class="p">(</span><span class="s1">'User'</span><span class="p">)</span><span class="o">-></span><span class="na">findBy</span><span class="p">(</span><span class="k">array</span><span class="p">(</span><span class="s1">'age'</span> <span class="o">=></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 'Miller'</span>
|
||
|
<span class="nv">$users</span> <span class="o">=</span> <span class="nv">$dm</span><span class="o">-></span><span class="na">getRepository</span><span class="p">(</span><span class="s1">'User'</span><span class="p">)</span><span class="o">-></span><span class="na">findBy</span><span class="p">(</span><span class="k">array</span><span class="p">(</span><span class="s1">'age'</span> <span class="o">=></span> <span class="mi">20</span><span class="p">,</span> <span class="s1">'surname'</span> <span class="o">=></span> <span class="s1">'Miller'</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">-></span><span class="na">getRepository</span><span class="p">(</span><span class="s1">'User'</span><span class="p">)</span><span class="o">-></span><span class="na">findOneBy</span><span class="p">(</span><span class="k">array</span><span class="p">(</span><span class="s1">'nickname'</span> <span class="o">=></span> <span class="s1">'romanb'</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"><?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">-></span><span class="na">getRepository</span><span class="p">(</span><span class="s1">'User'</span><span class="p">)</span><span class="o">-></span><span class="na">findOneBy</span><span class="p">(</span><span class="k">array</span><span class="p">(</span><span class="s1">'nickname'</span> <span class="o">=></span> <span class="s1">'romanb'</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">-></span><span class="na">getRepository</span><span class="p">(</span><span class="s1">'User'</span><span class="p">)</span><span class="o">-></span><span class="na">findOneByNickname</span><span class="p">(</span><span class="s1">'romanb'</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"><?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">-></span><span class="na">createQueryBuilder</span><span class="p">(</span><span class="s1">'User'</span><span class="p">)</span>
|
||
|
<span class="o">-></span><span class="na">field</span><span class="p">(</span><span class="s1">'age'</span><span class="p">)</span><span class="o">-></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">-></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">-></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"><?php</span>
|
||
|
|
||
|
<span class="nv">$group</span> <span class="o">=</span> <span class="nv">$dm</span><span class="o">-></span><span class="na">find</span><span class="p">(</span><span class="s1">'Group'</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">-></span><span class="na">createQueryBuilder</span><span class="p">(</span><span class="s1">'User'</span><span class="p">)</span>
|
||
|
<span class="o">-></span><span class="na">field</span><span class="p">(</span><span class="s1">'group'</span><span class="p">)</span><span class="o">-></span><span class="na">references</span><span class="p">(</span><span class="nv">$group</span><span class="p">)</span>
|
||
|
<span class="o">-></span><span class="na">getQuery</span><span class="p">()</span><span class="o">-></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"><?php</span>
|
||
|
|
||
|
<span class="nv">$users</span> <span class="o">=</span> <span class="nv">$dm</span><span class="o">-></span><span class="na">createQueryBuilder</span><span class="p">(</span><span class="s1">'User'</span><span class="p">)</span>
|
||
|
<span class="o">-></span><span class="na">field</span><span class="p">(</span><span class="s1">'groups'</span><span class="p">)</span><span class="o">-></span><span class="na">includesReferenceTo</span><span class="p">(</span><span class="nv">$group</span><span class="p">)</span>
|
||
|
<span class="o">-></span><span class="na">getQuery</span><span class="p">()</span><span class="o">-></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">
|
||
|
© 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>
|