<p dir="auto">Currently,</p>
<div class="highlight highlight-text-html-php notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="Validator\Mapping\MemberMetadata::accept() "><pre class="notranslate"><span class="pl-v">Validator</span>\<span class="pl-v">Mapping</span>\<span class="pl-v">MemberMetadata</span>::<span class="pl-en">accept</span>() </pre></div>
<p dir="auto">leaves traversing of properties that are arrays or \Traversable up to the visitor.<br>
While the main purpose of <em>Visitor Pattern</em> is to decouple object structure from visitor functionality.</p>
<p dir="auto">In the following example, i naively expected that, when visiting an entity, a MyValidationVisitor::vizit() method would be recursively invoked for every entity property.</p>
<div class="highlight highlight-text-html-php notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="$metadata = $validator-&gt;getMetadataFor($entity);

$visitor = new MyValidationVisitor();
$metadata-&gt;accept($visitor, $entity, ...);"><pre class="notranslate"><span class="pl-s1"><span class="pl-c1">$</span>metadata</span> = <span class="pl-s1"><span class="pl-c1">$</span>validator</span>-&gt;<span class="pl-en">getMetadataFor</span>(<span class="pl-s1"><span class="pl-c1">$</span>entity</span>);

<span class="pl-s1"><span class="pl-c1">$</span>visitor</span> = <span class="pl-k">new</span> <span class="pl-v">MyValidationVisitor</span>();
<span class="pl-s1"><span class="pl-c1">$</span>metadata</span>-&gt;<span class="pl-en">accept</span>(<span class="pl-s1"><span class="pl-c1">$</span>visitor</span>, <span class="pl-s1"><span class="pl-c1">$</span>entity</span>, ...);</pre></div>
<p dir="auto">In practice, i have to manually re-curse into array properties.</p>
<p dir="auto">I believe, that the need to call accept() inside Vizitor::visit() brings confusion, so the following code from Validator\ValidationVisitor::validate() method must be re-factored and moved to Validator\Mapping\MemberMetadata::accept() in order to decouple validation from structure of validated objects</p>
<div class="highlight highlight-text-html-php notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="if (is_array($value) || ($traverse &amp;&amp; $value instanceof \Traversable)) {
    foreach ($value as $key =&gt; $element) {
        // Ignore any scalar values in the collection
        if (is_object($element) || is_array($element)) {
            // Only repeat the traversal if $deep is set
            $this-&gt;validate($element, $group, $propertyPath.'['.$key.']', $deep, $deep);
        }
    }

    try {
        $this-&gt;metadataFactory-&gt;getMetadataFor($value)-&gt;accept($this, $value, $group, $propertyPath);
    } catch (NoSuchMetadataException $e) {
        // Metadata doesn't necessarily have to exist for
        // traversable objects, because we know how to validate
        // them anyway. Optionally, additional metadata is supported.
    }
} else {
    $this-&gt;metadataFactory-&gt;getMetadataFor($value)-&gt;accept($this, $value, $group, $propertyPath);
}"><pre class="notranslate"><span class="pl-k">if</span> (is_array(<span class="pl-s1"><span class="pl-c1">$</span>value</span>) || (<span class="pl-s1"><span class="pl-c1">$</span>traverse</span> &amp;&amp; <span class="pl-s1"><span class="pl-c1">$</span>value</span> instanceof \<span class="pl-v">Traversable</span>)) {
    <span class="pl-k">foreach</span> (<span class="pl-s1"><span class="pl-c1">$</span>value</span> <span class="pl-k">as</span> <span class="pl-s1"><span class="pl-c1">$</span>key</span> =&gt; <span class="pl-s1"><span class="pl-c1">$</span>element</span>) {
        <span class="pl-c">// Ignore any scalar values in the collection</span>
        <span class="pl-k">if</span> (is_object(<span class="pl-s1"><span class="pl-c1">$</span>element</span>) || is_array(<span class="pl-s1"><span class="pl-c1">$</span>element</span>)) {
            <span class="pl-c">// Only repeat the traversal if $deep is set</span>
            <span class="pl-s1"><span class="pl-c1">$</span><span class="pl-smi">this</span></span>-&gt;<span class="pl-en">validate</span>(<span class="pl-s1"><span class="pl-c1">$</span>element</span>, <span class="pl-s1"><span class="pl-c1">$</span>group</span>, <span class="pl-s1"><span class="pl-c1">$</span>propertyPath</span>.<span class="pl-s">'['</span>.<span class="pl-s1"><span class="pl-c1">$</span>key</span>.<span class="pl-s">']'</span>, <span class="pl-s1"><span class="pl-c1">$</span>deep</span>, <span class="pl-s1"><span class="pl-c1">$</span>deep</span>);
        }
    }

    <span class="pl-k">try</span> {
        <span class="pl-s1"><span class="pl-c1">$</span><span class="pl-smi">this</span></span>-&gt;<span class="pl-c1">metadataFactory</span>-&gt;<span class="pl-en">getMetadataFor</span>(<span class="pl-s1"><span class="pl-c1">$</span>value</span>)-&gt;<span class="pl-en">accept</span>(<span class="pl-s1"><span class="pl-c1">$</span><span class="pl-smi">this</span></span>, <span class="pl-s1"><span class="pl-c1">$</span>value</span>, <span class="pl-s1"><span class="pl-c1">$</span>group</span>, <span class="pl-s1"><span class="pl-c1">$</span>propertyPath</span>);
    } <span class="pl-k">catch</span> (<span class="pl-smi"><span class="pl-smi">NoSuchMetadataException</span></span> <span class="pl-s1"><span class="pl-c1">$</span>e</span>) {
        <span class="pl-c">// Metadata doesn't necessarily have to exist for</span>
        <span class="pl-c">// traversable objects, because we know how to validate</span>
        <span class="pl-c">// them anyway. Optionally, additional metadata is supported.</span>
    }
} <span class="pl-k">else</span> {
    <span class="pl-s1"><span class="pl-c1">$</span><span class="pl-smi">this</span></span>-&gt;<span class="pl-c1">metadataFactory</span>-&gt;<span class="pl-en">getMetadataFor</span>(<span class="pl-s1"><span class="pl-c1">$</span>value</span>)-&gt;<span class="pl-en">accept</span>(<span class="pl-s1"><span class="pl-c1">$</span><span class="pl-smi">this</span></span>, <span class="pl-s1"><span class="pl-c1">$</span>value</span>, <span class="pl-s1"><span class="pl-c1">$</span>group</span>, <span class="pl-s1"><span class="pl-c1">$</span>propertyPath</span>);
}</pre></div>
<p dir="auto">Currently there is a <code class="notranslate">@Route</code> annotation. But how could I easily add routes which are redirected to the main route to prevent duplicate content (Search Engine Optimization, redirect old routes, ..)?</p>
<p dir="auto">I think something like <code class="notranslate">@RedirectRoute("/test", "/target", 301)</code> would be nice.</p>