<table role="table">
<thead>
<tr>
<th>Q</th>
<th>A</th>
</tr>
</thead>
<tbody>
<tr>
<td>Bug report?</td>
<td>no</td>
</tr>
<tr>
<td>Feature request?</td>
<td>yes</td>
</tr>
<tr>
<td>BC Break report?</td>
<td>?</td>
</tr>
<tr>
<td>RFC?</td>
<td>yes</td>
</tr>
<tr>
<td>Symfony version</td>
<td>3.2</td>
</tr>
</tbody>
</table>
<p dir="auto">The system detects automatically the name of an adder or remover of a collection by an ENGLISH logic I guess. It relates a dependency to a human langage and not PHP... Moreover, I suppose it forces an execution time by parsing words or something else.</p>
<p dir="auto">For greater flexibility, it would be a good idea to let the developper what the developper has to do (understand and write its own HUMAN langage)... In my case, I have to use some specific French words for a collection, and my logic is broken by an english one. I think we would be able to set the adder and remover name in the annotation. By default, an english logic could be applyed, why not ?</p>
<p dir="auto">The <code class="notranslate">PropertyPath</code> class currently makes a list of assumptions:</p>
<h5 dir="auto">1. Objects are treated by reference</h5>
<p dir="auto">When the path <code class="notranslate">author.name</code> is modified, the following methods are called:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="getAuthor()
setName() // on the author"><pre class="notranslate"><code class="notranslate">getAuthor()
setName() // on the author
</code></pre></div>
<p dir="auto">Note that <code class="notranslate">setAuthor()</code> is not called.</p>
<h5 dir="auto">2. Adders and removers are used if they exist</h5>
<p dir="auto">If a collection is written into the path <code class="notranslate">tags</code> and the methods <code class="notranslate">addTag()</code> and <code class="notranslate">removeTag()</code> exist, these are used to merge into the old collection instead of accessing the old collection directly via its <code class="notranslate">ArrayAccess</code> interface. The following methods are called:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="getTags()
addTag(...) // instead of $tags[] = ...
removeTag(...) // instead of unset($tags[...])"><pre class="notranslate"><code class="notranslate">getTags()
addTag(...) // instead of $tags[] = ...
removeTag(...) // instead of unset($tags[...])
</code></pre></div>
<h5 dir="auto">3. Adders and removers follow English singularization rules</h5>
<p dir="auto">If a property path is called <code class="notranslate">children</code>, the guessed adders and removers are <code class="notranslate">addChild()</code> and <code class="notranslate">removeChild()</code>.</p>
<h5 dir="auto">Limitations</h5>
<p dir="auto">The above assumptions do not hold in all applications:</p>
<ol dir="auto">
<li>Sometimes setters should be called (no by-reference handling, see <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="10616028" data-permission-text="Title is private" data-url="https://github.com/symfony/symfony/issues/6965" data-hovercard-type="issue" data-hovercard-url="/symfony/symfony/issues/6965/hovercard" href="https://github.com/symfony/symfony/issues/6965">#6965</a>)</li>
<li>Sometimes elements should be written directly into collections even though adders/removers exist (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="4349742" data-permission-text="Title is private" data-url="https://github.com/symfony/symfony/issues/4158" data-hovercard-type="issue" data-hovercard-url="/symfony/symfony/issues/4158/hovercard" href="https://github.com/symfony/symfony/issues/4158">#4158</a>, <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="6216629" data-permission-text="Title is private" data-url="https://github.com/symfony/symfony/issues/5257" data-hovercard-type="pull_request" data-hovercard-url="/symfony/symfony/pull/5257/hovercard" href="https://github.com/symfony/symfony/pull/5257">#5257</a>)</li>
<li>For other languages than English, singularization does not work</li>
</ol>
<p dir="auto">So, these assumptions should be made configurable. The challenge is how to build this API in an intuitive way.</p>
<h5 dir="auto">Alternative 1: Option arrays</h5>
<p dir="auto">The first alternative is to pass the options in an array separately from the property path. For example:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="Path:    artikel.stichwörter (= article.tags)
Options: array(
             'artikel' =&gt; array(
                 'by_reference' =&gt; false,
             ),
             'artikel.stichwörter' =&gt; array(
                 'use_adders' =&gt; false,
                 // or
                 'singular' =&gt; 'stichwort',
             ),
         )"><pre class="notranslate"><code class="notranslate">Path:    artikel.stichwörter (= article.tags)
Options: array(
             'artikel' =&gt; array(
                 'by_reference' =&gt; false,
             ),
             'artikel.stichwörter' =&gt; array(
                 'use_adders' =&gt; false,
                 // or
                 'singular' =&gt; 'stichwort',
             ),
         )
</code></pre></div>
<h5 dir="auto">Alternative 2: Path flags</h5>
<p dir="auto">The second alternative is to build the configuration options into the path:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="artikel{!byref}.stichwörter{!adders}
// or
artikel{!byref}.stichwörter{singular=stichwort}"><pre class="notranslate"><code class="notranslate">artikel{!byref}.stichwörter{!adders}
// or
artikel{!byref}.stichwörter{singular=stichwort}
</code></pre></div>
<h5 dir="auto">Alternative 3: Your suggestions</h5>
<p dir="auto">Do you have any other ideas? What approach do you prefer?</p>