Tag manipulation using DOMDocument On our main symfony2 application at work I have had to manipulate some outputted grid fields by wrapping them in a hyperlink tag.  This happens in quite a few different controllers, so I made a method to do this to prevent code repetition.

I decided to do this using DOMDocument and construct the new hyperlink with that.

public function linkWrap($string, $route, array $route_params = [], $prefilter = null)
  {
    if(strlen($string) &gt; 0)
    {
      $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;
  }


The method takes a number of options the last of which is used only to append a prefilter query string for use with APYGridBundle.

My question is, does this cause a significantly larger overhead than just constructing the link in a more 'conventional' way?

As follows:

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


In addition, any tips on how any of could be improved would be appreciated.
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 ]));