mongodb-odm-docs-dash/build.docset/Contents/Resources/Documents/cookbook/soft-delete-extension.html

343 lines
22 KiB
HTML
Raw Permalink Normal View History

2017-12-02 03:35:11 +00:00
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>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>