<p dir="auto">People have voiced the need for form input filtering various times. Filtering could be added to the Form component very easily by creating an (optional) extension that enables the following API:</p>
<div class="highlight highlight-text-html-php notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="$builder-&gt;add('content', 'textarea', array(
    // a single filter or an array of filters
    'filters' =&gt; new StripTags(),
));"><pre class="notranslate"><span class="pl-s1"><span class="pl-c1">$</span>builder</span>-&gt;<span class="pl-en">add</span>(<span class="pl-s">'content'</span>, <span class="pl-s">'textarea'</span>, <span class="pl-en">array</span>(
    <span class="pl-c">// a single filter or an array of filters</span>
    <span class="pl-s">'filters'</span> =&gt; <span class="pl-k">new</span> <span class="pl-v">StripTags</span>(),
));</pre></div>
<p dir="auto">The big question is which library to use for filtering. Upon short research, I came upon two existing alternatives:</p>
<ul dir="auto">
<li><a href="https://github.com/zendframework/zf2/tree/master/library/Zend/Filter">Zend\Filter</a>
<ul dir="auto">
<li>appears mature</li>
<li>potentially brings in other ZF2 baggage, which I don't care about once ZF2 supports Composer properly and unless the baggage creates further disadvantages</li>
</ul>
</li>
<li><a href="https://github.com/rdohms/DMS-Filter">DMS-Filter</a>
<ul dir="auto">
<li>very young</li>
<li>supports annotation-based filtering in POPOs</li>
</ul>
</li>
</ul>
<p dir="auto">Does anyone know further filtering libraries? Does anyone have experience with Zend\Filter in non-ZF(2) projects?</p>
<h4 dir="auto">Comparison Sheet</h4>
<table role="table">
<tbody><tr>
<th>Zend\Filter</th>
<th>DMS-Filter</th>
<th>Comment</th>
</tr>
<tr>
<td>Alnum</td>
<td>Alnum</td>
<td>both support Unicode, Zend has special treatment for Japanese, Chinese and Korean</td>
</tr>
<tr>
<td>Alpha</td>
<td></td>
<td></td>
</tr>
<tr>
<td>Boolean</td>
<td>Boolean</td>
<td>DMS does a simple cast, Zend's implementation is more complicated, but supports localized "yes" and "no" as well as leaving the original value unchanged unless it evaluates to false (use case?)</td>
</tr>
<tr>
<td>Callback</td>
<td></td>
<td></td>
</tr>
<tr>
<td>Digits</td>
<td></td>
<td></td>
</tr>
<tr>
<td>File\LowerCase</td>
<td></td>
<td></td>
</tr>
<tr>
<td>File\Rename</td>
<td></td>
<td></td>
</tr>
<tr>
<td>File\UpperCase</td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>Float</td>
<td></td>
</tr>
<tr>
<td>HtmlEntities</td>
<td></td>
<td></td>
</tr>
<tr>
<td>Int</td>
<td>Int</td>
<td></td>
</tr>
<tr>
<td>PregReplace</td>
<td></td>
<td>supports Unicode</td>
</tr>
<tr>
<td>StringToLower</td>
<td>ToLower</td>
<td>both support Unicode</td>
</tr>
<tr>
<td>StringToUpper</td>
<td>ToUpper</td>
<td>both support Unicode</td>
</tr>
<tr>
<td>StringTrim</td>
<td>Trim</td>
<td>both allow the specification of a character list to be trimmed</td>
</tr>
<tr>
<td>StripNewlines</td>
<td>StripNewlines</td>
<td></td>
</tr>
<tr>
<td>StripTags</td>
<td>StripTags</td>
<td>Zend allows to specify allowed tags, attributes and comments; DMS only allowed tags (using `strip_tags` internally).</td>
</tr>
<tr>
<th colspan="3">Not a filter, but a transformer</th>
</tr><tr>
<td>BaseName</td>
<td></td>
<td></td>
</tr>
<tr>
<td>Compress</td>
<td></td>
<td>supports BZ2, GZ, LZF, RAR, TAR and ZIP</td>
</tr>
<tr>
<td>Decompress</td>
<td></td>
<td>see Compress</td>
</tr>
<tr>
<td>Decrypt</td>
<td></td>
<td>supports MCrypt and OpenSSL</td>
</tr>
<tr>
<td>Dir</td>
<td></td>
<td></td>
</tr>
<tr>
<td>Encrypt</td>
<td></td>
<td>see Decrypt</td>
</tr>
<tr>
<td>File\Decrypt</td>
<td></td>
<td>see Decrypt</td>
</tr>
<tr>
<td>File\Encrypt</td>
<td></td>
<td>see Decrypt</td>
</tr>
<tr>
<td>Null</td>
<td></td>
<td></td>
</tr>
<tr>
<td>RealPath</td>
<td></td>
<td></td>
</tr>
<tr>
<td>Word\CamelCaseToDash</td>
<td></td>
<td></td>
</tr>
<tr>
<td>Word\CamelCaseToSeparator</td>
<td></td>
<td></td>
</tr>
<tr>
<td>Word\CamelCaseToUnderscore</td>
<td></td>
<td></td>
</tr>
<tr>
<td>Word\DashToCamelCase</td>
<td></td>
<td></td>
</tr>
<tr>
<td>Word\DashToSeparator</td>
<td></td>
<td></td>
</tr>
<tr>
<td>Word\DashToUnderscore</td>
<td></td>
<td></td>
</tr>
<tr>
<td>Word\SeparatorToCamelCase</td>
<td></td>
<td></td>
</tr>
<tr>
<td>Word\SeparatorToDash</td>
<td></td>
<td></td>
</tr>
<tr>
<td>Word\SeparatorToSeparator</td>
<td></td>
<td></td>
</tr>
<tr>
<td>Word\UnderscoreToCamelCase</td>
<td></td>
<td></td>
</tr>
<tr>
<td>Word\UnderscoreToDash</td>
<td></td>
<td></td>
</tr>
<tr>
<td>Word\UnderscoreToSeparator</td>
<td></td>
<td></td>
</tr>
</tbody></table>
<p dir="auto"><strong>Description</strong><br>
In the past, services were public or private (I'm ignoring "synthetic" services and other edge cases):</p>
<ul dir="auto">
<li>Public: these are the services that you can use in your app. Also, you can <code class="notranslate">$this-&gt;get()</code> them in controllers.</li>
<li>Private: don't use these services in your own code! These are "internal" services created by Symfony or third-party bundles. In modern Symfony versions you can't get them with <code class="notranslate">$this-&gt;get()</code> because they have random service IDs.</li>
</ul>
<p dir="auto">Also, private services don't appear on <code class="notranslate">debug:container</code>. It makes sense.</p>
<p dir="auto"><strong>Problem</strong><br>
In recent Symfony versions we made all services private by default. In my opinion, the problem is that we don't really want to make services private. In fact, those services are used in your app, so their "nature" is to be public. We make them private so you can't do <code class="notranslate">$this-&gt;get()</code> to get them (and to unlock some performance improvements).</p>
<p dir="auto"><strong>Proposal</strong><br>
What if we do this:</p>
<ul dir="auto">
<li>Remove all features to get services with <code class="notranslate">$this-&gt;get()</code> in controllers and commands and force to always inject services. This is a BC break, only possible in Symfony 5.</li>
<li>Restore the previous behavior: all services are public, unless you make them private for some reason. Private services don't appear on <code class="notranslate">debug:container</code></li>
<li>Remove the concept of "hidden services", which are now "private services" again.</li>
</ul>