Trying a new generation script

This commit is contained in:
2017-12-01 20:06:23 -08:00
parent 59abc53bec
commit 4d1b823198
202 changed files with 5 additions and 5 deletions
@@ -0,0 +1,334 @@
<!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>Blending the ORM and MongoDB ODM &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="blending-the-orm-and-mongodb-odm">
<h1>Blending the ORM and MongoDB ODM<a class="headerlink" href="#blending-the-orm-and-mongodb-odm" title="Permalink to this headline"></a></h1>
<p>Since the start of the <a class="reference external" href="http://www.doctrine-project.org/projects/mongodb_odm">Doctrine MongoDB Object Document Mapper</a> project people have asked how it can be integrated with the <a class="reference external" href="http://www.doctrine-project.org/projects/orm">ORM</a>. This article will demonstrates how you can integrate the two transparently, maintaining a clean domain model.</p>
<p>This example will have a <cite>Product</cite> that is stored in MongoDB and the <cite>Order</cite> stored in a MySQL database.</p>
<div class="section" id="define-product">
<h2>Define Product<a class="headerlink" href="#define-product" title="Permalink to this headline"></a></h2>
<p>First lets define our <cite>Product</cite> document:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="k">namespace</span> <span class="nx">Documents</span><span class="p">;</span>
<span class="sd">/** @Document */</span>
<span class="k">class</span> <span class="nc">Product</span>
<span class="p">{</span>
<span class="sd">/** @Id */</span>
<span class="k">private</span> <span class="nv">$id</span><span class="p">;</span>
<span class="sd">/** @Field(type=&quot;string&quot;) */</span>
<span class="k">private</span> <span class="nv">$title</span><span class="p">;</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">getId</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">id</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">getTitle</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">title</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">setTitle</span><span class="p">(</span><span class="nv">$title</span><span class="p">)</span>
<span class="p">{</span>
<span class="nv">$this</span><span class="o">-&gt;</span><span class="na">title</span> <span class="o">=</span> <span class="nv">$title</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
</div>
<div class="section" id="define-entity">
<h2>Define Entity<a class="headerlink" href="#define-entity" title="Permalink to this headline"></a></h2>
<p>Next create the <cite>Order</cite> entity that has a <cite>$product</cite> and <cite>$productId</cite> property linking it to the <cite>Product</cite> that is stored with MongoDB:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="k">namespace</span> <span class="nx">Entities</span><span class="p">;</span>
<span class="k">use</span> <span class="nx">Documents\Product</span><span class="p">;</span>
<span class="sd">/**</span>
<span class="sd"> * @Entity</span>
<span class="sd"> * @Table(name=&quot;orders&quot;)</span>
<span class="sd"> */</span>
<span class="k">class</span> <span class="nc">Order</span>
<span class="p">{</span>
<span class="sd">/**</span>
<span class="sd"> * @Id @Column(type=&quot;integer&quot;)</span>
<span class="sd"> * @GeneratedValue(strategy=&quot;AUTO&quot;)</span>
<span class="sd"> */</span>
<span class="k">private</span> <span class="nv">$id</span><span class="p">;</span>
<span class="sd">/**</span>
<span class="sd"> * @Column(type=&quot;string&quot;)</span>
<span class="sd"> */</span>
<span class="k">private</span> <span class="nv">$productId</span><span class="p">;</span>
<span class="sd">/**</span>
<span class="sd"> * @var Documents\Product</span>
<span class="sd"> */</span>
<span class="k">private</span> <span class="nv">$product</span><span class="p">;</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">getId</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">id</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">getProductId</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">productId</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">setProduct</span><span class="p">(</span><span class="nx">Product</span> <span class="nv">$product</span><span class="p">)</span>
<span class="p">{</span>
<span class="nv">$this</span><span class="o">-&gt;</span><span class="na">productId</span> <span class="o">=</span> <span class="nv">$product</span><span class="o">-&gt;</span><span class="na">getId</span><span class="p">();</span>
<span class="nv">$this</span><span class="o">-&gt;</span><span class="na">product</span> <span class="o">=</span> <span class="nv">$product</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">getProduct</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">product</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
</div>
<div class="section" id="event-subscriber">
<h2>Event Subscriber<a class="headerlink" href="#event-subscriber" title="Permalink to this headline"></a></h2>
<p>Now we need to setup an event subscriber that will set the <cite>$product</cite> property of all <cite>Order</cite> instances to a reference to the document product so it can be lazily loaded when it is accessed the first time. So first register a new event subscriber:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nv">$eventManager</span> <span class="o">=</span> <span class="nv">$em</span><span class="o">-&gt;</span><span class="na">getEventManager</span><span class="p">();</span>
<span class="nv">$eventManager</span><span class="o">-&gt;</span><span class="na">addEventListener</span><span class="p">(</span>
<span class="k">array</span><span class="p">(</span><span class="nx">\Doctrine\ORM\Events</span><span class="o">::</span><span class="na">postLoad</span><span class="p">),</span> <span class="k">new</span> <span class="nx">MyEventSubscriber</span><span class="p">(</span><span class="nv">$dm</span><span class="p">)</span>
<span class="p">);</span>
</pre></div>
</div>
<p>So now we need to define a class named <cite>MyEventSubscriber</cite> and pass a dependency to the <cite>DocumentManager</cite>. It will have a <cite>postLoad()</cite> method that sets the product document reference:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="k">use</span> <span class="nx">Doctrine\ODM\MongoDB\DocumentManager</span><span class="p">;</span>
<span class="k">use</span> <span class="nx">Doctrine\ORM\Event\LifecycleEventArgs</span><span class="p">;</span>
<span class="k">class</span> <span class="nc">MyEventSubscriber</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">__construct</span><span class="p">(</span><span class="nx">DocumentManager</span> <span class="nv">$dm</span><span class="p">)</span>
<span class="p">{</span>
<span class="nv">$this</span><span class="o">-&gt;</span><span class="na">dm</span> <span class="o">=</span> <span class="nv">$dm</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">postLoad</span><span class="p">(</span><span class="nx">LifecycleEventArgs</span> <span class="nv">$eventArgs</span><span class="p">)</span>
<span class="p">{</span>
<span class="nv">$order</span> <span class="o">=</span> <span class="nv">$eventArgs</span><span class="o">-&gt;</span><span class="na">getEntity</span><span class="p">();</span>
<span class="nv">$em</span> <span class="o">=</span> <span class="nv">$eventArgs</span><span class="o">-&gt;</span><span class="na">getEntityManager</span><span class="p">();</span>
<span class="nv">$productReflProp</span> <span class="o">=</span> <span class="nv">$em</span><span class="o">-&gt;</span><span class="na">getClassMetadata</span><span class="p">(</span><span class="s1">&#39;Entities\Order&#39;</span><span class="p">)</span>
<span class="o">-&gt;</span><span class="na">reflClass</span><span class="o">-&gt;</span><span class="na">getProperty</span><span class="p">(</span><span class="s1">&#39;product&#39;</span><span class="p">);</span>
<span class="nv">$productReflProp</span><span class="o">-&gt;</span><span class="na">setAccessible</span><span class="p">(</span><span class="k">true</span><span class="p">);</span>
<span class="nv">$productReflProp</span><span class="o">-&gt;</span><span class="na">setValue</span><span class="p">(</span>
<span class="nv">$order</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">dm</span><span class="o">-&gt;</span><span class="na">getReference</span><span class="p">(</span><span class="s1">&#39;Documents\Product&#39;</span><span class="p">,</span> <span class="nv">$order</span><span class="o">-&gt;</span><span class="na">getProductId</span><span class="p">())</span>
<span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
<p>The <cite>postLoad</cite> method will be invoked after an ORM entity is loaded from the database. This allows us to use the <cite>DocumentManager</cite> to set the <cite>$product</cite> property with a reference to the <cite>Product</cite> document with the product id we previously stored.</p>
</div>
<div class="section" id="working-with-products-and-orders">
<h2>Working with Products and Orders<a class="headerlink" href="#working-with-products-and-orders" title="Permalink to this headline"></a></h2>
<p>First create a new <cite>Product</cite>:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nv">$product</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">\Documents\Product</span><span class="p">();</span>
<span class="nv">$product</span><span class="o">-&gt;</span><span class="na">setTitle</span><span class="p">(</span><span class="s1">&#39;Test Product&#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">$product</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>Now create a new <cite>Order</cite> and link it to a <cite>Product</cite> in MySQL:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nv">$order</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">\Entities\Order</span><span class="p">();</span>
<span class="nv">$order</span><span class="o">-&gt;</span><span class="na">setProduct</span><span class="p">(</span><span class="nv">$product</span><span class="p">);</span>
<span class="nv">$em</span><span class="o">-&gt;</span><span class="na">persist</span><span class="p">(</span><span class="nv">$order</span><span class="p">);</span>
<span class="nv">$em</span><span class="o">-&gt;</span><span class="na">flush</span><span class="p">();</span>
</pre></div>
</div>
<p>Later we can retrieve the entity and lazily load the reference to the document in MongoDB:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nv">$order</span> <span class="o">=</span> <span class="nv">$em</span><span class="o">-&gt;</span><span class="na">find</span><span class="p">(</span><span class="s1">&#39;Order&#39;</span><span class="p">,</span> <span class="nv">$order</span><span class="o">-&gt;</span><span class="na">getId</span><span class="p">());</span>
<span class="c1">// Instance of an uninitialized product proxy</span>
<span class="nv">$product</span> <span class="o">=</span> <span class="nv">$order</span><span class="o">-&gt;</span><span class="na">getProduct</span><span class="p">();</span>
<span class="c1">// Initializes proxy and queries the database</span>
<span class="k">echo</span> <span class="s2">&quot;Order Title: &quot;</span> <span class="o">.</span> <span class="nv">$product</span><span class="o">-&gt;</span><span class="na">getTitle</span><span class="p">();</span>
</pre></div>
</div>
<p>If you were to print the <cite>$order</cite> you would see that we got back regular PHP objects:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nb">print_r</span><span class="p">(</span><span class="nv">$order</span><span class="p">);</span>
</pre></div>
</div>
<p>The above would output the following:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="x">Order Object</span>
<span class="x">(</span>
<span class="x"> [id:Entities\Order:private] =&gt; 53</span>
<span class="x"> [productId:Entities\Order:private] =&gt; 4c74a1868ead0ed7a9000000</span>
<span class="x"> [product:Entities\Order:private] =&gt; Proxies\DocumentsProductProxy Object</span>
<span class="x"> (</span>
<span class="x"> [__isInitialized__] =&gt; 1</span>
<span class="x"> [id:Documents\Product:private] =&gt; 4c74a1868ead0ed7a9000000</span>
<span class="x"> [title:Documents\Product:private] =&gt; Test Product</span>
<span class="x"> )</span>
<span class="x">)</span>
</pre></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="#">Blending the ORM and MongoDB ODM</a><ul>
<li><a class="reference internal" href="#define-product">Define Product</a></li>
<li><a class="reference internal" href="#define-entity">Define Entity</a></li>
<li><a class="reference internal" href="#event-subscriber">Event Subscriber</a></li>
<li><a class="reference internal" href="#working-with-products-and-orders">Working with Products and Orders</a></li>
</ul>
</li>
</ul>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="../_sources/cookbook/blending-orm-and-mongodb-odm.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>
@@ -0,0 +1,264 @@
<!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>Implementing ArrayAccess for Domain 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="implementing-arrayaccess-for-domain-objects">
<h1>Implementing ArrayAccess for Domain Objects<a class="headerlink" href="#implementing-arrayaccess-for-domain-objects" title="Permalink to this headline"></a></h1>
<p><em>Section author: Roman Borschel (<a class="reference external" href="mailto:roman&#37;&#52;&#48;code-factory&#46;org">roman<span>&#64;</span>code-factory<span>&#46;</span>org</a>)</em></p>
<p>This recipe will show you how to implement ArrayAccess for your
domain objects in order to allow more uniform access, for example
in templates. In these examples we will implement ArrayAccess on a
<a class="reference external" href="http://martinfowler.com/eaaCatalog/layerSupertype.html">Layer Supertype</a>
for all our domain objects.</p>
<div class="section" id="option-1">
<h2>Option 1<a class="headerlink" href="#option-1" title="Permalink to this headline"></a></h2>
<p>In this implementation we will make use of PHPs highly dynamic
nature to dynamically access properties of a subtype in a supertype
at runtime. Note that this implementation has 2 main caveats:</p>
<ul class="simple">
<li>It will not work with private fields</li>
<li>It will not go through any getters/setters</li>
</ul>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="k">abstract</span> <span class="k">class</span> <span class="nc">DomainObject</span> <span class="k">implements</span> <span class="nx">ArrayAccess</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">offsetExists</span><span class="p">(</span><span class="nv">$offset</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">return</span> <span class="nb">isset</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="nv">$offset</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">offsetSet</span><span class="p">(</span><span class="nv">$offset</span><span class="p">,</span> <span class="nv">$value</span><span class="p">)</span>
<span class="p">{</span>
<span class="nv">$this</span><span class="o">-&gt;</span><span class="nv">$offset</span> <span class="o">=</span> <span class="nv">$value</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">offsetGet</span><span class="p">(</span><span class="nv">$offset</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="nv">$offset</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">offsetUnset</span><span class="p">(</span><span class="nv">$offset</span><span class="p">)</span>
<span class="p">{</span>
<span class="nv">$this</span><span class="o">-&gt;</span><span class="nv">$offset</span> <span class="o">=</span> <span class="k">null</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
</div>
<div class="section" id="option-2">
<h2>Option 2<a class="headerlink" href="#option-2" title="Permalink to this headline"></a></h2>
<p>In this implementation we will dynamically invoke getters/setters.
Again we use PHPs dynamic nature to invoke methods on a subtype
from a supertype at runtime. This implementation has the following
caveats:</p>
<ul class="simple">
<li>It relies on a naming convention</li>
<li>The semantics of offsetExists can differ</li>
<li>offsetUnset will not work with typehinted setters</li>
</ul>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="k">abstract</span> <span class="k">class</span> <span class="nc">DomainObject</span> <span class="k">implements</span> <span class="nx">ArrayAccess</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">offsetExists</span><span class="p">(</span><span class="nv">$offset</span><span class="p">)</span>
<span class="p">{</span>
<span class="c1">// In this example we say that exists means it is not null</span>
<span class="nv">$value</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="p">{</span><span class="s2">&quot;get</span><span class="si">$offset</span><span class="s2">&quot;</span><span class="p">}();</span>
<span class="k">return</span> <span class="nv">$value</span> <span class="o">!==</span> <span class="k">null</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">offsetSet</span><span class="p">(</span><span class="nv">$offset</span><span class="p">,</span> <span class="nv">$value</span><span class="p">)</span>
<span class="p">{</span>
<span class="nv">$this</span><span class="o">-&gt;</span><span class="p">{</span><span class="s2">&quot;set</span><span class="si">$offset</span><span class="s2">&quot;</span><span class="p">}(</span><span class="nv">$value</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">offsetGet</span><span class="p">(</span><span class="nv">$offset</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="p">{</span><span class="s2">&quot;get</span><span class="si">$offset</span><span class="s2">&quot;</span><span class="p">}();</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">offsetUnset</span><span class="p">(</span><span class="nv">$offset</span><span class="p">)</span>
<span class="p">{</span>
<span class="nv">$this</span><span class="o">-&gt;</span><span class="p">{</span><span class="s2">&quot;set</span><span class="si">$offset</span><span class="s2">&quot;</span><span class="p">}(</span><span class="k">null</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
</div>
<div class="section" id="read-only">
<h2>Read-only<a class="headerlink" href="#read-only" title="Permalink to this headline"></a></h2>
<p>You can slightly tweak option 1 or option 2 in order to make array
access read-only. This will also circumvent some of the caveats of
each option. Simply make offsetSet and offsetUnset throw an
exception (i.e. BadMethodCallException).</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="k">abstract</span> <span class="k">class</span> <span class="nc">DomainObject</span> <span class="k">implements</span> <span class="nx">ArrayAccess</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">offsetExists</span><span class="p">(</span><span class="nv">$offset</span><span class="p">)</span>
<span class="p">{</span>
<span class="c1">// option 1 or option 2</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">offsetSet</span><span class="p">(</span><span class="nv">$offset</span><span class="p">,</span> <span class="nv">$value</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nx">BadMethodCallException</span><span class="p">(</span><span class="s2">&quot;Array access of class &quot;</span> <span class="o">.</span> <span class="nb">get_class</span><span class="p">(</span><span class="nv">$this</span><span class="p">)</span> <span class="o">.</span> <span class="s2">&quot; is read-only!&quot;</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">offsetGet</span><span class="p">(</span><span class="nv">$offset</span><span class="p">)</span>
<span class="p">{</span>
<span class="c1">// option 1 or option 2</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">offsetUnset</span><span class="p">(</span><span class="nv">$offset</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nx">BadMethodCallException</span><span class="p">(</span><span class="s2">&quot;Array access of class &quot;</span> <span class="o">.</span> <span class="nb">get_class</span><span class="p">(</span><span class="nv">$this</span><span class="p">)</span> <span class="o">.</span> <span class="s2">&quot; is read-only!&quot;</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></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="#">Implementing ArrayAccess for Domain Objects</a><ul>
<li><a class="reference internal" href="#option-1">Option 1</a></li>
<li><a class="reference internal" href="#option-2">Option 2</a></li>
<li><a class="reference internal" href="#read-only">Read-only</a></li>
</ul>
</li>
</ul>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="../_sources/cookbook/implementing-array-access-for-domain-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>
@@ -0,0 +1,213 @@
<!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>Implementing the Notify ChangeTracking Policy &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="implementing-the-notify-changetracking-policy">
<h1>Implementing the Notify ChangeTracking Policy<a class="headerlink" href="#implementing-the-notify-changetracking-policy" title="Permalink to this headline"></a></h1>
<p><em>Section author: Roman Borschel (<a class="reference external" href="mailto:roman&#37;&#52;&#48;code-factory&#46;org">roman<span>&#64;</span>code-factory<span>&#46;</span>org</a>)</em></p>
<p>The NOTIFY change-tracking policy is the most effective
change-tracking policy provided by Doctrine but it requires some
boilerplate code. This recipe will show you how this boilerplate
code should look like. We will implement it on a
<a class="reference external" href="http://martinfowler.com/eaaCatalog/layerSupertype.html">Layer Supertype</a>
for all our domain objects.</p>
<div class="section" id="implementing-notifypropertychanged">
<h2>Implementing NotifyPropertyChanged<a class="headerlink" href="#implementing-notifypropertychanged" title="Permalink to this headline"></a></h2>
<p>The NOTIFY policy is based on the assumption that the entities
notify interested listeners of changes to their properties. For
that purpose, a class that wants to use this policy needs to
implement the <code class="docutils literal"><span class="pre">NotifyPropertyChanged</span></code> interface from the
<code class="docutils literal"><span class="pre">Doctrine\Common</span></code> namespace.</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="k">use</span> <span class="nx">Doctrine\Common\NotifyPropertyChanged</span><span class="p">,</span>
<span class="nx">Doctrine\Common\PropertyChangedListener</span><span class="p">;</span>
<span class="k">abstract</span> <span class="k">class</span> <span class="nc">DomainObject</span> <span class="k">implements</span> <span class="nx">NotifyPropertyChanged</span>
<span class="p">{</span>
<span class="k">private</span> <span class="nv">$_listeners</span> <span class="o">=</span> <span class="k">array</span><span class="p">();</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">addPropertyChangedListener</span><span class="p">(</span><span class="nx">PropertyChangedListener</span> <span class="nv">$listener</span><span class="p">)</span>
<span class="p">{</span>
<span class="nv">$this</span><span class="o">-&gt;</span><span class="na">_listeners</span><span class="p">[]</span> <span class="o">=</span> <span class="nv">$listener</span><span class="p">;</span>
<span class="p">}</span>
<span class="sd">/** Notifies listeners of a change. */</span>
<span class="k">protected</span> <span class="k">function</span> <span class="nf">_onPropertyChanged</span><span class="p">(</span><span class="nv">$propName</span><span class="p">,</span> <span class="nv">$oldValue</span><span class="p">,</span> <span class="nv">$newValue</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">_listeners</span><span class="p">)</span> <span class="p">{</span>
<span class="k">foreach</span> <span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">_listeners</span> <span class="k">as</span> <span class="nv">$listener</span><span class="p">)</span> <span class="p">{</span>
<span class="nv">$listener</span><span class="o">-&gt;</span><span class="na">propertyChanged</span><span class="p">(</span><span class="nv">$this</span><span class="p">,</span> <span class="nv">$propName</span><span class="p">,</span> <span class="nv">$oldValue</span><span class="p">,</span> <span class="nv">$newValue</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Then, in each property setter of concrete, derived domain classes,
you need to invoke _onPropertyChanged as follows to notify
listeners:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="c1">// Mapping not shown, either in annotations, xml or yaml as usual</span>
<span class="k">class</span> <span class="nc">MyEntity</span> <span class="k">extends</span> <span class="nx">DomainObject</span>
<span class="p">{</span>
<span class="k">private</span> <span class="nv">$data</span><span class="p">;</span>
<span class="c1">// ... other fields as usual</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">setData</span><span class="p">(</span><span class="nv">$data</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">$data</span> <span class="o">!=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">data</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// check: is it actually modified?</span>
<span class="nv">$this</span><span class="o">-&gt;</span><span class="na">_onPropertyChanged</span><span class="p">(</span><span class="s1">&#39;data&#39;</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">data</span><span class="p">,</span> <span class="nv">$data</span><span class="p">);</span>
<span class="nv">$this</span><span class="o">-&gt;</span><span class="na">data</span> <span class="o">=</span> <span class="nv">$data</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
<p>The check whether the new value is different from the old one is
not mandatory but recommended. That way you can avoid unnecessary
updates and also have full control over when you consider a
property changed.</p>
</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="#">Implementing the Notify ChangeTracking Policy</a><ul>
<li><a class="reference internal" href="#implementing-notifypropertychanged">Implementing NotifyPropertyChanged</a></li>
</ul>
</li>
</ul>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="../_sources/cookbook/implementing-the-notify-changetracking-policy.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>
@@ -0,0 +1,216 @@
<!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>Implementing Wakeup or Clone &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="implementing-wakeup-or-clone">
<h1>Implementing Wakeup or Clone<a class="headerlink" href="#implementing-wakeup-or-clone" title="Permalink to this headline"></a></h1>
<p><em>Section author: Roman Borschel (<a class="reference external" href="mailto:roman&#37;&#52;&#48;code-factory&#46;org">roman<span>&#64;</span>code-factory<span>&#46;</span>org</a>)</em></p>
<p>As explained in the
<a class="reference internal" href="../reference/architecture.html"><span class="doc">restrictions for document classes in the manual</span></a>.
it is usually not allowed for a document to implement <code class="docutils literal"><span class="pre">__wakeup</span></code>
or <code class="docutils literal"><span class="pre">__clone</span></code>, because Doctrine makes special use of them.
However, it is quite easy to make use of these methods in a safe
way by guarding the custom wakeup or clone code with a document
identity check, as demonstrated in the following sections.</p>
<div class="section" id="safely-implementing-wakeup">
<h2>Safely implementing __wakeup<a class="headerlink" href="#safely-implementing-wakeup" title="Permalink to this headline"></a></h2>
<p>To safely implement <code class="docutils literal"><span class="pre">__wakeup</span></code>, simply enclose your
implementation code in an identity check as follows:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="k">class</span> <span class="nc">MyDocument</span>
<span class="p">{</span>
<span class="k">private</span> <span class="nv">$id</span><span class="p">;</span> <span class="c1">// This is the identifier of the document.</span>
<span class="c1">//...</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">__wakeup</span><span class="p">()</span>
<span class="p">{</span>
<span class="c1">// If the document has an identity, proceed as normal.</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">id</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// ... Your code here as normal ...</span>
<span class="p">}</span>
<span class="c1">// otherwise do nothing, do NOT throw an exception!</span>
<span class="p">}</span>
<span class="c1">//...</span>
<span class="p">}</span>
</pre></div>
</div>
</div>
<div class="section" id="safely-implementing-clone">
<h2>Safely implementing __clone<a class="headerlink" href="#safely-implementing-clone" title="Permalink to this headline"></a></h2>
<p>Safely implementing <code class="docutils literal"><span class="pre">__clone</span></code> is pretty much the same:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="k">class</span> <span class="nc">MyDocument</span>
<span class="p">{</span>
<span class="k">private</span> <span class="nv">$id</span><span class="p">;</span> <span class="c1">// This is the identifier of the document.</span>
<span class="c1">//...</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">__clone</span><span class="p">()</span>
<span class="p">{</span>
<span class="c1">// If the document has an identity, proceed as normal.</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">id</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// ... Your code here as normal ...</span>
<span class="p">}</span>
<span class="c1">// otherwise do nothing, do NOT throw an exception!</span>
<span class="p">}</span>
<span class="c1">//...</span>
<span class="p">}</span>
</pre></div>
</div>
</div>
<div class="section" id="summary">
<h2>Summary<a class="headerlink" href="#summary" title="Permalink to this headline"></a></h2>
<p>As you have seen, it is quite easy to safely make use of
<code class="docutils literal"><span class="pre">__wakeup</span></code> and <code class="docutils literal"><span class="pre">__clone</span></code> in your documents without adding any
really Doctrine-specific or Doctrine-dependant code.</p>
<p>These implementations are possible and safe because when Doctrine
invokes these methods, the documents never have an identity (yet).
Furthermore, it is possibly a good idea to check for the identity
in your code anyway, since it's rarely the case that you want to
unserialize or clone a document with no identity.</p>
</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="#">Implementing Wakeup or Clone</a><ul>
<li><a class="reference internal" href="#safely-implementing-wakeup">Safely implementing __wakeup</a></li>
<li><a class="reference internal" href="#safely-implementing-clone">Safely implementing __clone</a></li>
<li><a class="reference internal" href="#summary">Summary</a></li>
</ul>
</li>
</ul>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="../_sources/cookbook/implementing-wakeup-or-clone.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>
@@ -0,0 +1,366 @@
<!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>Mapping Classes to the ORM and ODM &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="mapping-classes-to-the-orm-and-odm">
<h1>Mapping Classes to the ORM and ODM<a class="headerlink" href="#mapping-classes-to-the-orm-and-odm" title="Permalink to this headline"></a></h1>
<p>Because of the non intrusive design of Doctrine it is possible for you to have plain PHP classes
that are mapped to both a relational database with the Doctrine2 Object Relational Mapper and
MongoDB with the Doctrine MongoDB Object Document Mapper, or any other persistence layer that
implements the Doctrine Common <a class="reference external" href="https://github.com/doctrine/common/tree/master/lib/Doctrine/Common/Persistence">persistence</a> interfaces.</p>
<div class="section" id="test-subject">
<h2>Test Subject<a class="headerlink" href="#test-subject" title="Permalink to this headline"></a></h2>
<p>For this cookbook entry we need to define a class that can be persisted to both MySQL and MongoDB.
We'll use a <code class="docutils literal"><span class="pre">BlogPost</span></code> as you may want to write some generic blogging functionality that has support
for multiple Doctrine persistence layers:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="k">namespace</span> <span class="nx">Doctrine\Blog</span><span class="p">;</span>
<span class="k">class</span> <span class="nc">BlogPost</span>
<span class="p">{</span>
<span class="k">private</span> <span class="nv">$id</span><span class="p">;</span>
<span class="k">private</span> <span class="nv">$title</span><span class="p">;</span>
<span class="k">private</span> <span class="nv">$body</span><span class="p">;</span>
<span class="c1">// ...</span>
<span class="p">}</span>
</pre></div>
</div>
</div>
<div class="section" id="mapping-information">
<h2>Mapping Information<a class="headerlink" href="#mapping-information" title="Permalink to this headline"></a></h2>
<p>Now we just need to provide the mapping information for the Doctrine persistence layers so they know
how to consume the objects and persist them to the database.</p>
<div class="section" id="orm">
<h3>ORM<a class="headerlink" href="#orm" title="Permalink to this headline"></a></h3>
<p>First define the mapping for the ORM:</p>
<div class="configuration-block">
<ul class="simple">
<li><em>PHP</em><div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="k">namespace</span> <span class="nx">Doctrine\Blog</span><span class="p">;</span>
<span class="sd">/** @Entity(repositoryClass=&quot;Doctrine\Blog\ORM\BlogPostRepository&quot;) */</span>
<span class="k">class</span> <span class="nc">BlogPost</span>
<span class="p">{</span>
<span class="sd">/** @Id @Column(type=&quot;integer&quot;) */</span>
<span class="k">private</span> <span class="nv">$id</span><span class="p">;</span>
<span class="sd">/** @Column(type=&quot;string&quot;) */</span>
<span class="k">private</span> <span class="nv">$title</span><span class="p">;</span>
<span class="sd">/** @Column(type=&quot;text&quot;) */</span>
<span class="k">private</span> <span class="nv">$body</span><span class="p">;</span>
<span class="c1">// ...</span>
<span class="p">}</span>
</pre></div>
</div>
</li>
<li><em>XML</em><div class="highlight-xml"><div class="highlight"><pre><span class="cp">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="nt">&lt;doctrine-mapping</span> <span class="na">xmlns=</span><span class="s">&quot;http://doctrine-project.org/schemas/orm/doctrine-mapping&quot;</span>
<span class="na">xmlns:xsi=</span><span class="s">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span>
<span class="na">xsi:schemaLocation=</span><span class="s">&quot;http://doctrine-project.org/schemas/orm/doctrine-mapping</span>
<span class="s"> http://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;entity</span> <span class="na">name=</span><span class="s">&quot;Documents\BlogPost&quot;</span> <span class="na">repository-class=</span><span class="s">&quot;Doctrine\Blog\ORM\BlogPostRepository&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;id</span> <span class="na">name=</span><span class="s">&quot;id&quot;</span> <span class="na">type=</span><span class="s">&quot;integer&quot;</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;field</span> <span class="na">name=</span><span class="s">&quot;name&quot;</span> <span class="na">type=</span><span class="s">&quot;string&quot;</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;field</span> <span class="na">name=</span><span class="s">&quot;email&quot;</span> <span class="na">type=</span><span class="s">&quot;text&quot;</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;/entity&gt;</span>
<span class="nt">&lt;/doctrine-mapping&gt;</span>
</pre></div>
</div>
</li>
<li><em>YAML</em><div class="highlight-yaml"><div class="highlight"><pre><span class="l l-Scalar l-Scalar-Plain">Documents\BlogPost</span><span class="p p-Indicator">:</span>
<span class="l l-Scalar l-Scalar-Plain">repositoryClass</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">Doctrine\Blog\ORM\BlogPostRepository</span>
<span class="l l-Scalar l-Scalar-Plain">id</span><span class="p p-Indicator">:</span>
<span class="l l-Scalar l-Scalar-Plain">id</span><span class="p p-Indicator">:</span>
<span class="l l-Scalar l-Scalar-Plain">type</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">integer</span>
<span class="l l-Scalar l-Scalar-Plain">fields</span><span class="p p-Indicator">:</span>
<span class="l l-Scalar l-Scalar-Plain">title</span><span class="p p-Indicator">:</span>
<span class="l l-Scalar l-Scalar-Plain">type</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">string</span>
<span class="l l-Scalar l-Scalar-Plain">body</span><span class="p p-Indicator">:</span>
<span class="l l-Scalar l-Scalar-Plain">type</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">text</span>
</pre></div>
</div>
</li>
</ul>
</div>
<p>Now you are able to persist the <code class="docutils literal"><span class="pre">Documents\BlogPost</span></code> with an instance of <code class="docutils literal"><span class="pre">EntityManager</span></code>:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nv">$blogPost</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">BlogPost</span><span class="p">()</span>
<span class="nv">$blogPost</span><span class="o">-&gt;</span><span class="na">setTitle</span><span class="p">(</span><span class="s1">&#39;test&#39;</span><span class="p">);</span>
<span class="nv">$em</span><span class="o">-&gt;</span><span class="na">persist</span><span class="p">(</span><span class="nv">$blogPost</span><span class="p">);</span>
<span class="nv">$em</span><span class="o">-&gt;</span><span class="na">flush</span><span class="p">();</span>
</pre></div>
</div>
<p>You can find the blog post:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nv">$blogPost</span> <span class="o">=</span> <span class="nv">$em</span><span class="o">-&gt;</span><span class="na">getRepository</span><span class="p">(</span><span class="s1">&#39;Documents\BlogPost&#39;</span><span class="p">)</span><span class="o">-&gt;</span><span class="na">findOneByTitle</span><span class="p">(</span><span class="s1">&#39;test&#39;</span><span class="p">);</span>
</pre></div>
</div>
</div>
<div class="section" id="mongodb-odm">
<h3>MongoDB ODM<a class="headerlink" href="#mongodb-odm" title="Permalink to this headline"></a></h3>
<p>Now map the same class to the Doctrine MongoDB ODM:</p>
<div class="configuration-block">
<ul class="simple">
<li><em>PHP</em><div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="k">namespace</span> <span class="nx">Documents</span><span class="p">;</span>
<span class="sd">/** @Document(repositoryClass=&quot;Doctrine\Blog\ODM\MongoDB\BlogPostRepository&quot;) */</span>
<span class="k">class</span> <span class="nc">BlogPost</span>
<span class="p">{</span>
<span class="sd">/** @Id */</span>
<span class="k">private</span> <span class="nv">$id</span><span class="p">;</span>
<span class="sd">/** @Field(type=&quot;string&quot;) */</span>
<span class="k">private</span> <span class="nv">$title</span><span class="p">;</span>
<span class="sd">/** @Field(type=&quot;string&quot;) */</span>
<span class="k">private</span> <span class="nv">$body</span><span class="p">;</span>
<span class="c1">// ...</span>
<span class="p">}</span>
</pre></div>
</div>
</li>
<li><em>XML</em><div class="highlight-xml"><div class="highlight"><pre><span class="cp">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="nt">&lt;doctrine-mongo-mapping</span> <span class="na">xmlns=</span><span class="s">&quot;http://doctrine-project.org/schemas/orm/doctrine-mapping&quot;</span>
<span class="na">xmlns:xsi=</span><span class="s">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span>
<span class="na">xsi:schemaLocation=</span><span class="s">&quot;http://doctrine-project.org/schemas/orm/doctrine-mapping</span>
<span class="s"> http://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;document</span> <span class="na">name=</span><span class="s">&quot;Documents\BlogPost&quot;</span> <span class="na">repository-class=</span><span class="s">&quot;Doctrine\Blog\ODM\MongoDB\BlogPostRepository&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;field</span> <span class="na">fieldName=</span><span class="s">&quot;id&quot;</span> <span class="na">type=</span><span class="s">&quot;id&quot;</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;field</span> <span class="na">fieldName=</span><span class="s">&quot;name&quot;</span> <span class="na">type=</span><span class="s">&quot;string&quot;</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;field</span> <span class="na">fieldName=</span><span class="s">&quot;email&quot;</span> <span class="na">type=</span><span class="s">&quot;text&quot;</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;/document&gt;</span>
<span class="nt">&lt;/doctrine-mongo-mapping&gt;</span>
</pre></div>
</div>
</li>
<li><em>YAML</em><div class="highlight-yaml"><div class="highlight"><pre><span class="l l-Scalar l-Scalar-Plain">Documents\BlogPost</span><span class="p p-Indicator">:</span>
<span class="l l-Scalar l-Scalar-Plain">repositoryClass</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">Doctrine\Blog\ODM\MongoDB\BlogPostRepository</span>
<span class="l l-Scalar l-Scalar-Plain">fields</span><span class="p p-Indicator">:</span>
<span class="l l-Scalar l-Scalar-Plain">id</span><span class="p p-Indicator">:</span>
<span class="l l-Scalar l-Scalar-Plain">type</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">id</span>
<span class="l l-Scalar l-Scalar-Plain">title</span><span class="p p-Indicator">:</span>
<span class="l l-Scalar l-Scalar-Plain">type</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">string</span>
<span class="l l-Scalar l-Scalar-Plain">body</span><span class="p p-Indicator">:</span>
<span class="l l-Scalar l-Scalar-Plain">type</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">text</span>
</pre></div>
</div>
</li>
</ul>
</div>
<p>Now the same class is able to be persisted in the same way using an instance of <code class="docutils literal"><span class="pre">DocumentManager</span></code>:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nv">$blogPost</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">BlogPost</span><span class="p">()</span>
<span class="nv">$blogPost</span><span class="o">-&gt;</span><span class="na">setTitle</span><span class="p">(</span><span class="s1">&#39;test&#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">$blogPost</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>You can find the blog post:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nv">$blogPost</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;Documents\BlogPost&#39;</span><span class="p">)</span><span class="o">-&gt;</span><span class="na">findOneByTitle</span><span class="p">(</span><span class="s1">&#39;test&#39;</span><span class="p">);</span>
</pre></div>
</div>
</div>
</div>
<div class="section" id="repository-classes">
<h2>Repository Classes<a class="headerlink" href="#repository-classes" title="Permalink to this headline"></a></h2>
<p>You can implement the same repository interface for the ORM and MongoDB ODM easily:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="k">namespace</span> <span class="nx">Doctrine\Blog\ORM</span><span class="p">;</span>
<span class="k">use</span> <span class="nx">Doctrine\ORM\EntityRepository</span><span class="p">;</span>
<span class="k">class</span> <span class="nc">BlogPostRepository</span> <span class="k">extends</span> <span class="nx">EntityRepository</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">findPostById</span><span class="p">(</span><span class="nv">$id</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">return</span> <span class="nv">$this</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;id&#39;</span> <span class="o">=&gt;</span> <span class="nv">$id</span><span class="p">));</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Now define the same repository methods for the MongoDB ODM:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="k">namespace</span> <span class="nx">Doctrine\Blog\ODM\MongoDB</span><span class="p">;</span>
<span class="k">use</span> <span class="nx">Doctrine\ODM\MongoDB\DocumentRepository</span><span class="p">;</span>
<span class="k">class</span> <span class="nc">BlogPostRepository</span> <span class="k">extends</span> <span class="nx">DocumentRepository</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">findPostById</span><span class="p">(</span><span class="nv">$id</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">return</span> <span class="nv">$this</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;id&#39;</span> <span class="o">=&gt;</span> <span class="nv">$id</span><span class="p">));</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
<p>As you can see the repositories are the same and the final returned data is the same vanilla
PHP objects. The data is transparently injected to the objects for you automatically so you
are not forced to extend some base class or shape your domain in any certain way for it to work
with the Doctrine persistence layers.</p>
</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="#">Mapping Classes to the ORM and ODM</a><ul>
<li><a class="reference internal" href="#test-subject">Test Subject</a></li>
<li><a class="reference internal" href="#mapping-information">Mapping Information</a><ul>
<li><a class="reference internal" href="#orm">ORM</a></li>
<li><a class="reference internal" href="#mongodb-odm">MongoDB ODM</a></li>
</ul>
</li>
<li><a class="reference internal" href="#repository-classes">Repository Classes</a></li>
</ul>
</li>
</ul>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="../_sources/cookbook/mapping-classes-to-orm-and-odm.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>
@@ -0,0 +1,271 @@
<!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>Keeping Your Modules Independent &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="keeping-your-modules-independent">
<h1>Keeping Your Modules Independent<a class="headerlink" href="#keeping-your-modules-independent" title="Permalink to this headline"></a></h1>
<p>One of the goals of using modules is to create discrete units of functionality
that do not have many (if any) dependencies, allowing you to use that
functionality in other applications without including unnecessary items.</p>
<p>Doctrine MongoDB ODM includes a utility called
<code class="docutils literal"><span class="pre">ResolveTargetDocumentListener</span></code>, that functions by intercepting certain calls
inside Doctrine and rewriting <code class="docutils literal"><span class="pre">targetDocument</span></code> parameters in your metadata
mapping at runtime. This allows your bundle to use an interface or abstract
class in its mappings while still allowing the mapping to resolve to a concrete
document class at runtime.</p>
<p>This functionality allows you to define relationships between different
documents without creating hard dependencies.</p>
<div class="section" id="background">
<h2>Background<a class="headerlink" href="#background" title="Permalink to this headline"></a></h2>
<p>In the following example, we have an <cite>InvoiceModule</cite> that provides invoicing
functionality, and a <cite>CustomerModule</cite> that contains customer management tools.
We want to keep these separated, because they can be used in other systems
without each other; however, we'd like to use them together in our application.</p>
<p>In this case, we have an <code class="docutils literal"><span class="pre">Invoice</span></code> document with a relationship to a
non-existent object, an <code class="docutils literal"><span class="pre">InvoiceSubjectInterface</span></code>. The goal is to get
the <code class="docutils literal"><span class="pre">ResolveTargetDocumentListener</span></code> to replace any mention of the interface
with a real class that implements that interface.</p>
</div>
<div class="section" id="configuration">
<h2>Configuration<a class="headerlink" href="#configuration" title="Permalink to this headline"></a></h2>
<p>We're going to use the following basic documents (which are incomplete
for brevity) to explain how to set up and use the
<code class="docutils literal"><span class="pre">ResolveTargetDocumentListener</span></code>.</p>
<p>A Customer document:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="c1">// src/Acme/AppModule/Document/Customer.php</span>
<span class="k">namespace</span> <span class="nx">Acme\AppModule\Document</span><span class="p">;</span>
<span class="k">use</span> <span class="nx">Doctrine\ODM\MongoDB\Mapping\Annotations</span> <span class="k">as</span> <span class="nx">ODM</span><span class="p">;</span>
<span class="k">use</span> <span class="nx">Acme\CustomerModule\Document\Customer</span> <span class="k">as</span> <span class="nx">BaseCustomer</span><span class="p">;</span>
<span class="k">use</span> <span class="nx">Acme\InvoiceModule\Model\InvoiceSubjectInterface</span><span class="p">;</span>
<span class="sd">/**</span>
<span class="sd"> * @ODM\Document</span>
<span class="sd"> */</span>
<span class="k">class</span> <span class="nc">Customer</span> <span class="k">extends</span> <span class="nx">BaseCustomer</span> <span class="k">implements</span> <span class="nx">InvoiceSubjectInterface</span>
<span class="p">{</span>
<span class="c1">// In our example, any methods defined in the InvoiceSubjectInterface</span>
<span class="c1">// are already implemented in the BaseCustomer</span>
<span class="p">}</span>
</pre></div>
</div>
<p>An Invoice document:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="c1">// src/Acme/InvoiceModule/Document/Invoice.php</span>
<span class="k">namespace</span> <span class="nx">Acme\InvoiceModule\Document</span><span class="p">;</span>
<span class="k">use</span> <span class="nx">Doctrine\ODM\MongoDB\Mapping\Annotations</span> <span class="k">as</span> <span class="nx">ODM</span><span class="p">;</span>
<span class="k">use</span> <span class="nx">Acme\InvoiceModule\Model\InvoiceSubjectInterface</span><span class="p">;</span>
<span class="sd">/**</span>
<span class="sd"> * @ODM\Document</span>
<span class="sd"> */</span>
<span class="k">class</span> <span class="nc">Invoice</span>
<span class="p">{</span>
<span class="sd">/**</span>
<span class="sd"> * @ODM\ReferenceOne(targetDocument=&quot;Acme\InvoiceModule\Model\InvoiceSubjectInterface&quot;)</span>
<span class="sd"> * @var InvoiceSubjectInterface</span>
<span class="sd"> */</span>
<span class="k">protected</span> <span class="nv">$subject</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
<p>An InvoiceSubjectInterface:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="c1">// src/Acme/InvoiceModule/Model/InvoiceSubjectInterface.php</span>
<span class="k">namespace</span> <span class="nx">Acme\InvoiceModule\Model</span><span class="p">;</span>
<span class="sd">/**</span>
<span class="sd"> * An interface that the invoice Subject object should implement.</span>
<span class="sd"> * In most circumstances, only a single object should implement</span>
<span class="sd"> * this interface as the ResolveTargetDocumentListener can only</span>
<span class="sd"> * change the target to a single object.</span>
<span class="sd"> */</span>
<span class="k">interface</span> <span class="nx">InvoiceSubjectInterface</span>
<span class="p">{</span>
<span class="c1">// List any additional methods that your InvoiceModule</span>
<span class="c1">// will need to access on the subject so that you can</span>
<span class="c1">// be sure that you have access to those methods.</span>
<span class="sd">/**</span>
<span class="sd"> * @return string</span>
<span class="sd"> */</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">getName</span><span class="p">();</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Next, we need to configure the listener. Add this to the area where you setup
Doctrine MongoDB ODM. You must set this up in the way outlined below, otherwise
you cannot be guaranteed that the targetDocument resolution will occur reliably:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nv">$evm</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">\Doctrine\Common\EventManager</span><span class="p">;</span>
<span class="nv">$rtdl</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">\Doctrine\ODM\MongoDB\Tools\ResolveTargetDocumentListener</span><span class="p">;</span>
<span class="c1">// Adds a target-document class</span>
<span class="nv">$rtdl</span><span class="o">-&gt;</span><span class="na">addResolveTargetDocument</span><span class="p">(</span>
<span class="s1">&#39;Acme\\InvoiceModule\\Model\\InvoiceSubjectInterface&#39;</span><span class="p">,</span>
<span class="s1">&#39;Acme\\CustomerModule\\Document\\Customer&#39;</span><span class="p">,</span>
<span class="k">array</span><span class="p">()</span>
<span class="p">);</span>
<span class="c1">// Add the ResolveTargetDocumentListener</span>
<span class="nv">$evm</span><span class="o">-&gt;</span><span class="na">addEventListener</span><span class="p">(</span><span class="nx">\Doctrine\ODM\MongoDB\Events</span><span class="o">::</span><span class="na">loadClassMetadata</span><span class="p">,</span> <span class="nv">$rtdl</span><span class="p">);</span>
<span class="c1">// Create the document manager as you normally would</span>
<span class="nv">$dm</span> <span class="o">=</span> <span class="nx">\Doctrine\ODM\MongoDB\DocumentManager</span><span class="o">::</span><span class="na">create</span><span class="p">(</span><span class="nv">$connectionOptions</span><span class="p">,</span> <span class="nv">$config</span><span class="p">,</span> <span class="nv">$evm</span><span class="p">);</span>
</pre></div>
</div>
</div>
<div class="section" id="final-thoughts">
<h2>Final Thoughts<a class="headerlink" href="#final-thoughts" title="Permalink to this headline"></a></h2>
<p>With <code class="docutils literal"><span class="pre">ResolveTargetDocumentListener</span></code>, we are able to decouple our bundles so
that they are usable by themselves and easier to maintain independently, while
still being able to define relationships between different objects.</p>
</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="#">Keeping Your Modules Independent</a><ul>
<li><a class="reference internal" href="#background">Background</a></li>
<li><a class="reference internal" href="#configuration">Configuration</a></li>
<li><a class="reference internal" href="#final-thoughts">Final Thoughts</a></li>
</ul>
</li>
</ul>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="../_sources/cookbook/resolve-target-document-listener.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>
@@ -0,0 +1,300 @@
<!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>Simple Search Engine &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="simple-search-engine">
<h1>Simple Search Engine<a class="headerlink" href="#simple-search-engine" title="Permalink to this headline"></a></h1>
<p>It is very easy to implement a simple keyword search engine with MongoDB. Because of
its flexible schema less nature we can store the keywords we want to search through directly
on the document. MongoDB is capable of indexing the embedded documents so the results are fast
and scalable.</p>
<div class="section" id="sample-model-product">
<h2>Sample Model: Product<a class="headerlink" href="#sample-model-product" title="Permalink to this headline"></a></h2>
<p>Imagine you had a <code class="docutils literal"><span class="pre">Product</span></code> document and you want to search the products by keywords. You can
setup a document like the following with a <code class="docutils literal"><span class="pre">$keywords</span></code> property that is mapped as a collection:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="k">namespace</span> <span class="nx">Documents</span><span class="p">;</span>
<span class="sd">/** @Document */</span>
<span class="k">class</span> <span class="nc">Product</span>
<span class="p">{</span>
<span class="sd">/** @Id */</span>
<span class="k">private</span> <span class="nv">$id</span><span class="p">;</span>
<span class="sd">/** @Field(type=&quot;string&quot;) */</span>
<span class="k">private</span> <span class="nv">$title</span><span class="p">;</span>
<span class="sd">/** @Field(type=&quot;collection&quot;) @Index */</span>
<span class="k">private</span> <span class="nv">$keywords</span> <span class="o">=</span> <span class="k">array</span><span class="p">();</span>
<span class="c1">// ...</span>
<span class="p">}</span>
</pre></div>
</div>
</div>
<div class="section" id="working-with-keywords">
<h2>Working with Keywords<a class="headerlink" href="#working-with-keywords" title="Permalink to this headline"></a></h2>
<p>Now, create a product and add some keywords:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nv">$product</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Product</span><span class="p">();</span>
<span class="nv">$product</span><span class="o">-&gt;</span><span class="na">setTitle</span><span class="p">(</span><span class="s1">&#39;Nike Air Jordan 2011&#39;</span><span class="p">);</span>
<span class="nv">$product</span><span class="o">-&gt;</span><span class="na">addKeyword</span><span class="p">(</span><span class="s1">&#39;nike shoes&#39;</span><span class="p">);</span>
<span class="nv">$product</span><span class="o">-&gt;</span><span class="na">addKeyword</span><span class="p">(</span><span class="s1">&#39;jordan shoes&#39;</span><span class="p">);</span>
<span class="nv">$product</span><span class="o">-&gt;</span><span class="na">addKeyword</span><span class="p">(</span><span class="s1">&#39;air jordan&#39;</span><span class="p">);</span>
<span class="nv">$product</span><span class="o">-&gt;</span><span class="na">addKeyword</span><span class="p">(</span><span class="s1">&#39;shoes&#39;</span><span class="p">);</span>
<span class="nv">$product</span><span class="o">-&gt;</span><span class="na">addKeyword</span><span class="p">(</span><span class="s1">&#39;2011&#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">$product</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 above example populates the keywords manually but you could very easily write some code which
automatically generates your keywords from a string built by the Product that may include the title,
description and other fields. You could also use a tool like the <a class="reference external" href="http://www.alchemyapi.com">AlchemyAPI</a> if you want to do
some more intelligent keyword extraction.</p>
</div>
<div class="section" id="searching-keywords">
<h2>Searching Keywords<a class="headerlink" href="#searching-keywords" title="Permalink to this headline"></a></h2>
<p>Searching the keywords in the <code class="docutils literal"><span class="pre">Product</span></code> collection is easy! You can run a query like the following
to find documents that have at least one of the keywords:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nv">$keywords</span> <span class="o">=</span> <span class="k">array</span><span class="p">(</span><span class="s1">&#39;nike shoes&#39;</span><span class="p">,</span> <span class="s1">&#39;air jordan&#39;</span><span class="p">);</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;Product&#39;</span><span class="p">)</span>
<span class="o">-&gt;</span><span class="na">field</span><span class="p">(</span><span class="s1">&#39;keywords&#39;</span><span class="p">)</span><span class="o">-&gt;</span><span class="na">in</span><span class="p">(</span><span class="nv">$keywords</span><span class="p">);</span>
</pre></div>
</div>
<p>You can make the query more strict by using the <code class="docutils literal"><span class="pre">all()</span></code> method instead of <code class="docutils literal"><span class="pre">in()</span></code>:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nv">$keywords</span> <span class="o">=</span> <span class="k">array</span><span class="p">(</span><span class="s1">&#39;nike shoes&#39;</span><span class="p">,</span> <span class="s1">&#39;air jordan&#39;</span><span class="p">);</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;Product&#39;</span><span class="p">)</span>
<span class="o">-&gt;</span><span class="na">field</span><span class="p">(</span><span class="s1">&#39;keywords&#39;</span><span class="p">)</span><span class="o">-&gt;</span><span class="na">all</span><span class="p">(</span><span class="nv">$keywords</span><span class="p">);</span>
</pre></div>
</div>
<p>The above query would only return products that have both of the keywords!</p>
<div class="section" id="user-input">
<h3>User Input<a class="headerlink" href="#user-input" title="Permalink to this headline"></a></h3>
<p>You can easily build keywords from a user search form by exploding whitespace and passing
the results to your query. Here is an example:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nv">$queryString</span> <span class="o">=</span> <span class="nv">$_REQUEST</span><span class="p">[</span><span class="s1">&#39;q&#39;</span><span class="p">];</span>
<span class="nv">$keywords</span> <span class="o">=</span> <span class="nb">explode</span><span class="p">(</span><span class="s1">&#39; &#39;</span><span class="p">,</span> <span class="nv">$queryString</span><span class="p">);</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;Product&#39;</span><span class="p">)</span>
<span class="o">-&gt;</span><span class="na">field</span><span class="p">(</span><span class="s1">&#39;keywords&#39;</span><span class="p">)</span><span class="o">-&gt;</span><span class="na">all</span><span class="p">(</span><span class="nv">$keywords</span><span class="p">);</span>
</pre></div>
</div>
</div>
</div>
<div class="section" id="embedded-documents">
<h2>Embedded Documents<a class="headerlink" href="#embedded-documents" title="Permalink to this headline"></a></h2>
<p>If you want to use an embedded document instead of just an array then you can. It will allow you to store
additional information with each keyword, like its weight.</p>
<div class="section" id="definition">
<h3>Definition<a class="headerlink" href="#definition" title="Permalink to this headline"></a></h3>
<p>You can setup a <code class="docutils literal"><span class="pre">Keyword</span></code> document like the following:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="sd">/** @EmbeddedDocument */</span>
<span class="k">class</span> <span class="nc">Keyword</span>
<span class="p">{</span>
<span class="sd">/** @Field(type=&quot;string&quot;) @Index */</span>
<span class="k">private</span> <span class="nv">$keyword</span><span class="p">;</span>
<span class="sd">/** @Field(type=&quot;int&quot;) */</span>
<span class="k">private</span> <span class="nv">$weight</span><span class="p">;</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">__construct</span><span class="p">(</span><span class="nv">$keyword</span><span class="p">,</span> <span class="nv">$weight</span><span class="p">)</span>
<span class="p">{</span>
<span class="nv">$this</span><span class="o">-&gt;</span><span class="na">keyword</span> <span class="o">=</span> <span class="nv">$keyword</span><span class="p">;</span>
<span class="nv">$this</span><span class="o">-&gt;</span><span class="na">weight</span> <span class="o">=</span> <span class="nv">$weight</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">// ...</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Now you can embed the <code class="docutils literal"><span class="pre">Keyword</span></code> document many times in the <code class="docutils literal"><span class="pre">Product</span></code>:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="k">namespace</span> <span class="nx">Documents</span><span class="p">;</span>
<span class="sd">/** @Document */</span>
<span class="k">class</span> <span class="nc">Product</span>
<span class="p">{</span>
<span class="c1">// ...</span>
<span class="sd">/** @EmbedMany(targetDocument=&quot;Keyword&quot;) */</span>
<span class="k">private</span> <span class="nv">$keywords</span><span class="p">;</span>
<span class="c1">// ...</span>
<span class="p">}</span>
</pre></div>
</div>
<p>With the new embedded document to add a keyword to a <code class="docutils literal"><span class="pre">Product</span></code> the API is a little different,
you would have to do the following:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nv">$product</span><span class="o">-&gt;</span><span class="na">addKeyword</span><span class="p">(</span><span class="k">new</span> <span class="nx">Keyword</span><span class="p">(</span><span class="s1">&#39;nike shoes&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">));</span>
</pre></div>
</div>
<p>This is a very basic search engine example and can work for many small and simple applications. If you
need better searching functionality you can look at integrating something like <a class="reference external" href="http://lucene.apache.org/solr">Solr</a> in your project.</p>
</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="#">Simple Search Engine</a><ul>
<li><a class="reference internal" href="#sample-model-product">Sample Model: Product</a></li>
<li><a class="reference internal" href="#working-with-keywords">Working with Keywords</a></li>
<li><a class="reference internal" href="#searching-keywords">Searching Keywords</a><ul>
<li><a class="reference internal" href="#user-input">User Input</a></li>
</ul>
</li>
<li><a class="reference internal" href="#embedded-documents">Embedded Documents</a><ul>
<li><a class="reference internal" href="#definition">Definition</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="../_sources/cookbook/simple-search-engine.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>
@@ -0,0 +1,343 @@
<!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>Soft Delete Extension &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="soft-delete-extension">
<h1>Soft Delete Extension<a class="headerlink" href="#soft-delete-extension" title="Permalink to this headline"></a></h1>
<p>Sometimes you may not want to delete data from your database completely, but you want to
disable or temporarily delete some records so they do not appear anymore in your frontend.
Then, later you might want to restore that deleted data like it was never deleted.</p>
<p>This is possible with the <code class="docutils literal"><span class="pre">SoftDelete</span></code> extension which can be found on <a class="reference external" href="https://github.com/doctrine/mongodb-odm-softdelete">github</a>.</p>
<div class="section" id="installation">
<h2>Installation<a class="headerlink" href="#installation" title="Permalink to this headline"></a></h2>
<p>First you just need to get the code by cloning the <a class="reference external" href="https://github.com/doctrine/mongodb-odm-softdelete">github</a> repository:</p>
<div class="highlight-console"><div class="highlight"><pre><span class="gp">$</span> git clone git://github.com/doctrine/mongodb-odm-softdelete.git
</pre></div>
</div>
<p>Now once you have the code you can setup the autoloader for it:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nv">$classLoader</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ClassLoader</span><span class="p">(</span><span class="s1">&#39;Doctrine\ODM\MongoDB\SoftDelete&#39;</span><span class="p">,</span> <span class="s1">&#39;mongodb-odm-softdelete/lib&#39;</span><span class="p">);</span>
<span class="nv">$classLoader</span><span class="o">-&gt;</span><span class="na">register</span><span class="p">();</span>
</pre></div>
</div>
</div>
<div class="section" id="setup">
<h2>Setup<a class="headerlink" href="#setup" title="Permalink to this headline"></a></h2>
<p>Now you can autoload the classes you need to setup the <code class="docutils literal"><span class="pre">SoftDeleteManager</span></code> instance you need to manage
the soft delete state of your documents:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="k">use</span> <span class="nx">Doctrine\ODM\MongoDB\SoftDelete\Configuration</span><span class="p">;</span>
<span class="k">use</span> <span class="nx">Doctrine\ODM\MongoDB\SoftDelete\UnitOfWork</span><span class="p">;</span>
<span class="k">use</span> <span class="nx">Doctrine\ODM\MongoDB\SoftDelete\SoftDeleteManager</span><span class="p">;</span>
<span class="k">use</span> <span class="nx">Doctrine\Common\EventManager</span><span class="p">;</span>
<span class="c1">// $dm is a DocumentManager instance we should already have</span>
<span class="nv">$config</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Configuration</span><span class="p">();</span>
<span class="nv">$evm</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">EventManager</span><span class="p">();</span>
<span class="nv">$sdm</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">SoftDeleteManager</span><span class="p">(</span><span class="nv">$dm</span><span class="p">,</span> <span class="nv">$config</span><span class="p">,</span> <span class="nv">$evm</span><span class="p">);</span>
</pre></div>
</div>
</div>
<div class="section" id="softdeleteable-interface">
<h2>SoftDeleteable Interface<a class="headerlink" href="#softdeleteable-interface" title="Permalink to this headline"></a></h2>
<p>In order for your documents to work with the SoftDelete functionality they must implement
the <code class="docutils literal"><span class="pre">SoftDeleteable</span></code> interface:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="k">interface</span> <span class="nx">SoftDeleteable</span>
<span class="p">{</span>
<span class="k">function</span> <span class="nf">getDeletedAt</span><span class="p">();</span>
<span class="p">}</span>
</pre></div>
</div>
</div>
<div class="section" id="example-implementation">
<h2>Example Implementation<a class="headerlink" href="#example-implementation" title="Permalink to this headline"></a></h2>
<p>An implementation might look like this in a <code class="docutils literal"><span class="pre">User</span></code> document:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="k">use</span> <span class="nx">Doctrine\ODM\MongoDB\SoftDelete\SoftDeleteable</span><span class="p">;</span>
<span class="sd">/** @mongodb:Document */</span>
<span class="k">class</span> <span class="nc">User</span> <span class="k">implements</span> <span class="nx">SoftDeleteable</span>
<span class="p">{</span>
<span class="c1">// ...</span>
<span class="sd">/** @mongodb:Date @mongodb:Index */</span>
<span class="k">private</span> <span class="nv">$deletedAt</span><span class="p">;</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">getDeletedAt</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">deletedAt</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">// ...</span>
<span class="p">}</span>
</pre></div>
</div>
</div>
<div class="section" id="usage">
<h2>Usage<a class="headerlink" href="#usage" title="Permalink to this headline"></a></h2>
<p>Once you have the <code class="docutils literal"><span class="pre">$sdm</span></code> you can start managing the soft delete state of your documents:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nv">$jwage</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">findOneByUsername</span><span class="p">(</span><span class="s1">&#39;jwage&#39;</span><span class="p">);</span>
<span class="nv">$fabpot</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">findOneByUsername</span><span class="p">(</span><span class="s1">&#39;fabpot&#39;</span><span class="p">);</span>
<span class="nv">$sdm</span><span class="o">-&gt;</span><span class="na">delete</span><span class="p">(</span><span class="nv">$jwage</span><span class="p">);</span>
<span class="nv">$sdm</span><span class="o">-&gt;</span><span class="na">delete</span><span class="p">(</span><span class="nv">$fabpot</span><span class="p">);</span>
<span class="nv">$sdm</span><span class="o">-&gt;</span><span class="na">flush</span><span class="p">();</span>
</pre></div>
</div>
<p>The call to <code class="docutils literal"><span class="pre">SoftDeleteManager#flush()</span></code> would persist the deleted state to the database
for all the documents it knows about and run a query like the following:</p>
<div class="highlight-javascript"><div class="highlight"><pre><span class="nx">db</span><span class="p">.</span><span class="nx">users</span><span class="p">.</span><span class="nx">update</span><span class="p">({</span> <span class="nx">_id</span> <span class="o">:</span> <span class="p">{</span> <span class="nx">$in</span> <span class="o">:</span> <span class="nx">userIds</span> <span class="p">}},</span> <span class="p">{</span> <span class="nx">$set</span> <span class="o">:</span> <span class="p">{</span> <span class="nx">deletedAt</span> <span class="o">:</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">()</span> <span class="p">}</span> <span class="p">})</span>
</pre></div>
</div>
<p>Now if we were to restore the documents:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nv">$sdm</span><span class="o">-&gt;</span><span class="na">restore</span><span class="p">(</span><span class="nv">$jwage</span><span class="p">);</span>
<span class="nv">$sdm</span><span class="o">-&gt;</span><span class="na">flush</span><span class="p">();</span>
</pre></div>
</div>
<p>It would execute a query like the following:</p>
<div class="highlight-javascript"><div class="highlight"><pre><span class="nx">db</span><span class="p">.</span><span class="nx">users</span><span class="p">.</span><span class="nx">update</span><span class="p">({</span> <span class="nx">_id</span> <span class="o">:</span> <span class="p">{</span> <span class="nx">$in</span> <span class="o">:</span> <span class="nx">userIds</span> <span class="p">}},</span> <span class="p">{</span> <span class="nx">$unset</span> <span class="o">:</span> <span class="p">{</span> <span class="nx">deletedAt</span> <span class="o">:</span> <span class="kc">true</span> <span class="p">}</span> <span class="p">})</span>
</pre></div>
</div>
</div>
<div class="section" id="events">
<h2>Events<a class="headerlink" href="#events" title="Permalink to this headline"></a></h2>
<p>We trigger some additional lifecycle events when documents are soft deleted and restored:</p>
<ul class="simple">
<li>Events::preSoftDelete</li>
<li>Events::postSoftDelete</li>
<li>Events::preRestore</li>
<li>Events::postRestore</li>
</ul>
<p>Using the events is easy, just define a class like the following:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="k">class</span> <span class="nc">TestEventSubscriber</span> <span class="k">implements</span> <span class="nx">\Doctrine\Common\EventSubscriber</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">preSoftDelete</span><span class="p">(</span><span class="nx">LifecycleEventArgs</span> <span class="nv">$args</span><span class="p">)</span>
<span class="p">{</span>
<span class="nv">$document</span> <span class="o">=</span> <span class="nv">$args</span><span class="o">-&gt;</span><span class="na">getDocument</span><span class="p">();</span>
<span class="nv">$sdm</span> <span class="o">=</span> <span class="nv">$args</span><span class="o">-&gt;</span><span class="na">getSoftDeleteManager</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">getSubscribedEvents</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">return</span> <span class="k">array</span><span class="p">(</span><span class="nx">Events</span><span class="o">::</span><span class="na">preSoftDelete</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Now we just need to add the event subscriber to the EventManager:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nv">$eventSubscriber</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">TestEventSubscriber</span><span class="p">();</span>
<span class="nv">$evm</span><span class="o">-&gt;</span><span class="na">addEventSubscriber</span><span class="p">(</span><span class="nv">$eventSubscriber</span><span class="p">);</span>
</pre></div>
</div>
<p>When we soft delete something the preSoftDelete() method will be invoked before any queries are sent
to the database:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="nv">$sdm</span><span class="o">-&gt;</span><span class="na">delete</span><span class="p">(</span><span class="nv">$fabpot</span><span class="p">);</span>
<span class="nv">$sdm</span><span class="o">-&gt;</span><span class="na">flush</span><span class="p">();</span>
</pre></div>
</div>
</div>
<div class="section" id="cascading-soft-deletes">
<h2>Cascading Soft Deletes<a class="headerlink" href="#cascading-soft-deletes" title="Permalink to this headline"></a></h2>
<p>You can easily implement cascading soft deletes by using events in a certain way. Imagine you have
a User and Post document and you want to soft delete a users posts when you delete him.</p>
<p>You just need to setup an event listener like the following:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="k">use</span> <span class="nx">Doctrine\Common\EventSubscriber</span><span class="p">;</span>
<span class="k">use</span> <span class="nx">Doctrine\ODM\MongoDB\SoftDelete\Event\LifecycleEventArgs</span><span class="p">;</span>
<span class="k">class</span> <span class="nc">CascadingSoftDeleteListener</span> <span class="k">implements</span> <span class="nx">EventSubscriber</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">preSoftDelete</span><span class="p">(</span><span class="nx">LifecycleEventArgs</span> <span class="nv">$args</span><span class="p">)</span>
<span class="p">{</span>
<span class="nv">$sdm</span> <span class="o">=</span> <span class="nv">$args</span><span class="o">-&gt;</span><span class="na">getSoftDeleteManager</span><span class="p">();</span>
<span class="nv">$document</span> <span class="o">=</span> <span class="nv">$args</span><span class="o">-&gt;</span><span class="na">getDocument</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">$document</span> <span class="nx">instanceof</span> <span class="nx">User</span><span class="p">)</span> <span class="p">{</span>
<span class="nv">$sdm</span><span class="o">-&gt;</span><span class="na">deleteBy</span><span class="p">(</span><span class="s1">&#39;Post&#39;</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">&#39;user.id&#39;</span> <span class="o">=&gt;</span> <span class="nv">$document</span><span class="o">-&gt;</span><span class="na">getId</span><span class="p">()));</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">preRestore</span><span class="p">(</span><span class="nx">LifecycleEventArgs</span> <span class="nv">$args</span><span class="p">)</span>
<span class="p">{</span>
<span class="nv">$sdm</span> <span class="o">=</span> <span class="nv">$args</span><span class="o">-&gt;</span><span class="na">getSoftDeleteManager</span><span class="p">();</span>
<span class="nv">$document</span> <span class="o">=</span> <span class="nv">$args</span><span class="o">-&gt;</span><span class="na">getDocument</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">$document</span> <span class="nx">instanceof</span> <span class="nx">User</span><span class="p">)</span> <span class="p">{</span>
<span class="nv">$sdm</span><span class="o">-&gt;</span><span class="na">restoreBy</span><span class="p">(</span><span class="s1">&#39;Post&#39;</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">&#39;user.id&#39;</span> <span class="o">=&gt;</span> <span class="nv">$document</span><span class="o">-&gt;</span><span class="na">getId</span><span class="p">()));</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">getSubscribedEvents</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">return</span> <span class="k">array</span><span class="p">(</span>
<span class="nx">Events</span><span class="o">::</span><span class="na">preSoftDelete</span><span class="p">,</span>
<span class="nx">Events</span><span class="o">::</span><span class="na">preRestore</span>
<span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Now when you delete an instance of User it will also delete any Post documents where they
reference the User being deleted. If you restore the User, his Post documents will also be restored.</p>
</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="#">Soft Delete Extension</a><ul>
<li><a class="reference internal" href="#installation">Installation</a></li>
<li><a class="reference internal" href="#setup">Setup</a></li>
<li><a class="reference internal" href="#softdeleteable-interface">SoftDeleteable Interface</a></li>
<li><a class="reference internal" href="#example-implementation">Example Implementation</a></li>
<li><a class="reference internal" href="#usage">Usage</a></li>
<li><a class="reference internal" href="#events">Events</a></li>
<li><a class="reference internal" href="#cascading-soft-deletes">Cascading Soft Deletes</a></li>
</ul>
</li>
</ul>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="../_sources/cookbook/soft-delete-extension.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>
@@ -0,0 +1,256 @@
<!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>Validation of Documents &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="validation-of-documents">
<h1>Validation of Documents<a class="headerlink" href="#validation-of-documents" title="Permalink to this headline"></a></h1>
<p><em>Section author: Benjamin Eberlei &lt;<a class="reference external" href="mailto:kontakt&#37;&#52;&#48;beberlei&#46;de">kontakt<span>&#64;</span>beberlei<span>&#46;</span>de</a>&gt;</em></p>
<p>Doctrine does not ship with any internal validators, the reason
being that we think all the frameworks out there already ship with
quite decent ones that can be integrated into your Domain easily.
What we offer are hooks to execute any kind of validation.</p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">You don't need to validate your documents in the lifecycle
events. Its only one of many options. Of course you can also
perform validations in value setters or any other method of your
documents that are used in your code.</p>
</div>
<p>Documents can register lifecycle event methods with Doctrine that
are called on different occasions. For validation we would need to
hook into the events called before persisting and updating. Even
though we don't support validation out of the box, the
implementation is even simpler than in Doctrine 1 and you will get
the additional benefit of being able to re-use your validation in
any other part of your domain.</p>
<p>Say we have an <code class="docutils literal"><span class="pre">Order</span></code> with several <code class="docutils literal"><span class="pre">OrderLine</span></code> instances. We
never want to allow any customer to order for a larger sum than he
is allowed to:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="k">class</span> <span class="nc">Order</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">assertCustomerAllowedBuying</span><span class="p">()</span>
<span class="p">{</span>
<span class="nv">$orderLimit</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">customer</span><span class="o">-&gt;</span><span class="na">getOrderLimit</span><span class="p">();</span>
<span class="nv">$amount</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">foreach</span> <span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">orderLines</span> <span class="k">AS</span> <span class="nv">$line</span><span class="p">)</span> <span class="p">{</span>
<span class="nv">$amount</span> <span class="o">+=</span> <span class="nv">$line</span><span class="o">-&gt;</span><span class="na">getAmount</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">$amount</span> <span class="o">&gt;</span> <span class="nv">$orderLimit</span><span class="p">)</span> <span class="p">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nx">CustomerOrderLimitExceededException</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Now this is some pretty important piece of business logic in your
code, enforcing it at any time is important so that customers with
a unknown reputation don't owe your business too much money.</p>
<p>We can enforce this constraint in any of the metadata drivers.
First Annotations:</p>
<div class="configuration-block">
<ul class="simple">
<li><em>PHP</em><div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="sd">/** @Document @HasLifecycleCallbacks */</span>
<span class="k">class</span> <span class="nc">Order</span>
<span class="p">{</span>
<span class="sd">/** @PrePersist @PreUpdate */</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">assertCustomerAllowedBuying</span><span class="p">()</span> <span class="p">{}</span>
<span class="p">}</span>
</pre></div>
</div>
</li>
<li><em>XML</em><div class="highlight-xml"><div class="highlight"><pre><span class="nt">&lt;doctrine-mapping&gt;</span>
<span class="nt">&lt;document</span> <span class="na">name=</span><span class="s">&quot;Order&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;lifecycle-callbacks&gt;</span>
<span class="nt">&lt;lifecycle-callback</span> <span class="na">type=</span><span class="s">&quot;prePersist&quot;</span> <span class="na">method=</span><span class="s">&quot;assertCustomerallowedBuying&quot;</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;lifecycle-callback</span> <span class="na">type=</span><span class="s">&quot;preUpdate&quot;</span> <span class="na">method=</span><span class="s">&quot;assertCustomerallowedBuying&quot;</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;/lifecycle-callbacks&gt;</span>
<span class="nt">&lt;/document&gt;</span>
<span class="nt">&lt;/doctrine-mapping&gt;</span>
</pre></div>
</div>
</li>
</ul>
</div>
<p>Now validation is performed whenever you call
<code class="docutils literal"><span class="pre">DocumentManager#persist($order)</span></code> or when you call
<code class="docutils literal"><span class="pre">DocumentManager#flush()</span></code> and an order is about to be updated. Any
Exception that happens in the lifecycle callbacks will be cached by
the DocumentManager and the current transaction is rolled back.</p>
<p>Of course you can do any type of primitive checks, not null,
email-validation, string size, integer and date ranges in your
validation callbacks.</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>
<span class="sd">/** @Document @HasLifecycleCallbacks */</span>
<span class="k">class</span> <span class="nc">Order</span>
<span class="p">{</span>
<span class="sd">/** @PrePersist @PreUpdate */</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">validate</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">plannedShipDate</span> <span class="nx">instanceof</span> <span class="nx">DateTime</span><span class="p">))</span> <span class="p">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nx">ValidateException</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">plannedShipDate</span><span class="o">-&gt;</span><span class="na">format</span><span class="p">(</span><span class="s1">&#39;U&#39;</span><span class="p">)</span> <span class="o">&lt;</span> <span class="nb">time</span><span class="p">())</span> <span class="p">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nx">ValidateException</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">customer</span> <span class="o">==</span> <span class="k">null</span><span class="p">)</span> <span class="p">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nx">OrderRequiresCustomerException</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
<p>What is nice about lifecycle events is, you can also re-use the
methods at other places in your domain, for example in combination
with your form library. Additionally there is no limitation in the
number of methods you register on one particular event, i.e. you
can register multiple methods for validation in &quot;PrePersist&quot; or
&quot;PreUpdate&quot; or mix and share them in any combinations between those
two events.</p>
<p>There is no limit to what you can and can't validate in
&quot;PrePersist&quot; and &quot;PreUpdate&quot; as long as you don't create new document
instances. This was already discussed in the previous blog post on
the Versionable extension, which requires another type of event
called &quot;onFlush&quot;.</p>
<p>Further readings: <a class="reference internal" href="../reference/events.html"><span class="doc">Lifecycle Events</span></a></p>
</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>This Page</h3>
<ul class="this-page-menu">
<li><a href="../_sources/cookbook/validation-of-documents.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>