Tag manipulation using DOMDocument
Creating links using DOMDocument makes no sense to me. 

I have created a simple benchmark for both methods.

Simple string concatenation is around 7 times faster on my computer:




Method Name          Iterations    Average Time      Ops/second
------------------  ------------  --------------    -------------
simpleLink        : [10,000    ] [0.0000013786793] [725,331.85764]
linkUseDomDocument: [10,000    ] [0.0000098103762] [101,932.89054]



You could reuse objects in (for example) static variables like this:



public function linkWrap2($string, $route, array $route_params = [], $prefilter = null)
{
    static $dom = null, $new_hyper = null;

    if(strlen($string) &gt; 0)
    {
        if ($dom === null) {
            $dom = new \DOMDocument();
            $new_hyper = $dom-&gt;createElement('a');
        }

        $new_hyper-&gt;setAttribute('href', $this-&gt;generateUrl($route, $route_params).(isset($prefilter) ? '?'.htmlspecialchars($prefilter) : ''));
        $new_hyper-&gt;nodeValue = $string;

        return $dom-&gt;saveHTML($new_hyper);
    }

    return $string;
}


but it's only 30% faster.

My observations

Don't use htmlspecialchars in setAttribute value, because it will be encoded twice:

$new_hyper-&gt;setAttribute('href', $this-&gt;generateUrl($route, $route_params).(isset($prefilter) ? '?'.($prefilter) : ''));


However, you must use htmlspecialchars in simple concatenated strings:

$link = "&lt;a href=" . $this-&gt;generateUrl('a_route', array('id' =&gt; 23)) . '?'.htmlspecialchars($prefilter).'"&gt;some text&lt;/a&gt;';


Try to avoid custom query strings after a generated route URL. Instead of place value of $prefilter after the URL, you could place additional route params:

$this-&gt;generateUrl($route, array_merge($route_params, [ 'prefilter' =&gt; $prefilter ]));