HTML Pagination Generator I have created a function that helps me generate pagination really easily but I am concerned about its performance mainly.

The function accepts 2 parameters:


A list of items (has meaning in the framework I'm using) which contains information about the state of pagination itself and state of the storage layer - more precisely:


page the current page
perpage how many items are being shown per page
total the total amount of items in storage.

Parameter name - allows to customize the query string parameter key, which is by default named page - http://example.com/news?page=1.




public function paginationControls(BaseList $list, $parameter = 'page') {

    if (!isset($list-&gt;pagination)) {
        return 'Error: List has not been supplied with pagination details.';
    }

    // if total results are less than the results displayed on each page
    // then do not render controls
    if ($list-&gt;pagination-&gt;perpage &gt;= $list-&gt;pagination-&gt;total) {
        return null;
    }

    // Keep track of current query string parameters
    $query = trim(preg_replace('/' . $parameter . '\=\d+\&amp;?/', '', $_SERVER['QUERY_STRING']), '&amp;');
    if (strlen($query)) {
        $query .= '&amp;';
    }
    $query .= $parameter . '=';

    $makeanchor = function($page, $current = false) use ($query) {
        if ($current) {
            $url = '#';
            $class = 'pagination anchor current';
        } else {
            $url = '?' . $query . $page;
            $class = 'pagination anchor';
        }

        return $this-&gt;a($url, $page + 1, null, ['class' =&gt; $class]);
    };

    $page = $list-&gt;pagination-&gt;page;
    $pages = ceil($list-&gt;pagination-&gt;total / $list-&gt;pagination-&gt;perpage);

    // If page is greater than 3 then display link to first page
    $output = $page &gt; 3 ? ($makeanchor(0) . ' ... ') : '';

    // Add controls for 3 pages before current page
    $tmp = '';
    for ($i = 1; $i &lt;= 3 &amp;&amp; $page - $i &gt;= 0; $i++) {
        $tmp = $makeanchor($page - $i) . $tmp;
    }

    // Add current page indicator
    $output .= $tmp . $makeanchor($page, true);

    // Add controls for 3 pages after current page
    for ($i = 1; $i &lt;= 3 &amp;&amp; $page + $i + 1 &lt;= $pages; $i++) {
        $output .= $makeanchor($page + $i);
    }

    // If there are more than 3 pages after the current page
    // Then add control for last page
    if ($page + $i &lt; $pages) {
        $output .= ' ... ' . $makeanchor($pages - 1);
    }

    return $output;
}


And here are the respective helper functions

public function a($url, $text = null, $target = null, array $attributes = array()) {

    $attributes['href'] = $url;

    if ($target !== null) {
        $attributes['target'] = $target;
    }

    if ($text === null) {
        $text = $attributes['href'];
    }

    return '&lt;a' . $this-&gt;parseAttributes($attributes) . '&gt;' . html($text) . '&lt;/a&gt;';
}

private function parseAttributes($attributes) {
    $string = '';

    foreach ($attributes as $attribute =&gt; $value) {
        $string .= ' ' . html($attribute) . '="' . html($value) . '"';
    }

    return $string;
}


In a class far, far away

function html($string, $flag = ENT_QUOTES, $encoding = 'UTF-8') {
    return htmlspecialchars($string, $flag, $encoding);
}


I'm mainly interested in optimizing this function in terms of performance, it would be very much appreciated if someone more experienced than me can have a say on this.
Your code looks clean. The suggested changes below mainly focuses on reducing it a bit, so IMO improving its readability.
But I'm not quite sure it'll also improve performance as you said you're interested to: I only hope some light gain could come from having suppressed your $makeanchor() function.

Changes I propose affect only your main paginationControl() function:

public function paginationControls(BaseList $list, $parameter = 'page') {

    if (!isset($list-&gt;pagination)) {
        return 'Error: List has not been supplied with pagination details.';
    }

    // if total results are less than the results displayed on each page
    // then do not render controls
    if ($list-&gt;pagination-&gt;perpage &gt;= $list-&gt;pagination-&gt;total) {
        return null;
    }

    // Keep track of current query string parameters
    $query = preg_replace('/' . $parameter . '\=\d+\&amp;?/', '', $_SERVER['QUERY_STRING']);
    if ($query) {
        $query .= '&amp;';
    }
    $query .= $parameter . '=';

    $page = $list-&gt;pagination-&gt;page;
    $pages = ceil($list-&gt;pagination-&gt;total / $list-&gt;pagination-&gt;perpage);

    // Prepare link to first page, if needed
    if ($page &gt; 3) {
      $pageSet['1...'] = FALSE;
    }
    // Prepare link to 3 pages before + current + 3 pages after
    for ($i = $page - 3; $i &lt;= $page + 3; $i++) {
      if ($i AND $i &lt;= $pages) {
        $pageSet[$i] = ($i == $page);
      }
    }
    // Prepare link to last page, if needed
    if ($i &lt; $pages) {
      $pageSet['...' . $pages] = FALSE;
    }

    // Build output
    $output = NULL;
    $classes = 'pagination anchor';
    foreach ($pageSet as $pageNo =&gt; $current) {
      $output .= $this-&gt;a(
        ($current ? '#' : '?' . $query . $pageNo),
        $pageNo,
        NULL,
        ($classes . ($current ? 'current' : NULL))
      );
    }

    return $output;
}


Apart from the way to build pagination, you'll notice that:


I dropped trim(..., '&amp;') from your $query = ..., since "&amp;" has already suppressed by preg_replace(); otherwise it sounds like you suspect the whole query to abusively include an ending "&amp;"
at the just next line, I dropped strlen() from if ($query), which is enough (and may be slightly faster, but it is only cosmetic)