views:

57

answers:

4

The problem is that when I load page 2 for example the URL becomes:

http://domain.com/index.php?restaurant-id=45&currentpage=2

And that's fine but when I get to page 3 it becomes:

http://domain.com/index.php?restaurant-id=45&currentpage=2&currentpage=3

And so on, it adds one more currentpage parameter everytime a new page is loaded from the pagination links!

I wonder how this problem can be fixed?

Here's some of the pagination function's code

 /******  build the pagination links ******/
// Getting current page URL with its parameters
$current_page_url = ($_SERVER["PHP_SELF"].(isset($_SERVER["QUERY_STRING"])?"?".htmlentities($_SERVER["QUERY_STRING"]):""));
// Determine which sign to use (? or &) before the (currentpage=xx) parameter
$sign = preg_match('/\?/', $current_page_url) ? '&' : '?';

$pagination_links = '';
// if not on page 1, don't show back links
if ($currentpage > 1) {
   // show << link to go back to page 1
   $pagination_links .= " <a href='{$current_page_url}{$sign}currentpage=1'>First page</a> ";
   // get previous page num
   $prevpage = $currentpage - 1;
   // show < link to go back 1 page
   $pagination_links .= " <a href='{$current_page_url}{$sign}currentpage=$prevpage'>previous</a> ";
}
else
{
    $pagination_links .= "ـ ـ"; 
}// end if 
A: 

You need to remove the previous value from the query string, e.g.:

preg_replace('/&currentpage=\\d+/', '', $_SERVER["QUERY_STRING"]);

instead of just $_SERVER["QUERY_STRING"].

I prefer to use a class like this to manipulate the query string:

final class QueryString
{
    private $data;

    private function __construct($start=null) {
        if ($start === null)
            $this->data = $_GET;
        elseif (!is_array($start))
            throw new InvalidArgumentException();
    }

    public function __isset($nm) {
        return isset($this->data[$nm]);
    }

    public function __unset($nm) {
        unset($this->data[$nm]);
    }

    public function __get($nm) {
        return isset($this->data[$nm])?$this->data[$nm]:"";
    }

    public function __set($nm, $val) {
        $this->data[$nm] = $val;
    }

    public function getString() {
        return $this->getStringInternal(false);
    }

    public function getStringHTML() {
        return $this->getStringInternal(true);
    }  

    public function __toString() {
        return $this->getString();
    }

    private function getStringInternal($HTML=false) {
        if (empty($this->data))
            return "";

        $res = "?";        
        foreach ($this->data as $k => $v) {
            if (!is_array($v)) {
                if ($v === "")
                    $res .= urlencode($k).'&';
                else
                    $res .= urlencode($k)."=".urlencode($v).'&';
            }
            else
                foreach ($v as $vv) {
                    $res .= urlencode($k)."[]=".urlencode($vv).'&';
                }
        }

        $res = substr($res,0,-1);
        if ($HTML)
            $res = htmlspecialchars($res);

        return $res;
    }
}

Then I can just do:

$qs = new QueryString();
$qs->currentpage = 7;
$url = "list.php" . $qs;

It will keep all the previous parameters, create "currentpage" if it doesn't exist and modify it if it exists.

Note: you can replace the loop of getStringInternal with http_build_query if you wish. I don't like the behavior of http_build_query when a key has several values; I prefer "a=1&a=2" to "a[0]=1&a[1]=2" and the original didn't add "[]" to the key; however PHP doesn't support multiple values without brackets in the key very well (I have to manualy parse the query string), Java web services I sometimes interface with do).

Artefacto
man its GREAT code.
Col. Shrapnel
A: 

You could remove currentpage parameter from $current_page_url variable with regex although it's ugly.

$current_page_url = preg_replace('currentpage=\d+', '', $current_page_url);

However I'd suggest writing a small function that will generate URLs on the values you pass to it and then you can easily modify any parameter without having to worry about regexes and removing them from the URL. Something like this should be fine.

RaYell
+2  A: 

You could use http_build_query() for this. It's much cleaner than deleting the old parameter by hand.

It should be possible to pass a merged array consiting of $_GET and your new values, and get a clean URL.

Untested (can't test right now) but should work:

$new_data = array("currentpage" => "mypage.html");
$full_data = array_merge($_GET, $new_data);  // New data will overwrite old entry
$url = http_build_query($full_data);
Pekka
A: 

I would do this more nicer

$params = $_GET;
if(isset($params['currentpage'])) unset($params['currentpage']);
$pagination_links = '';
for($i = 1; $i <= 5; $i++){ // lets make 5 links for example
    $pagination_links.= '<a href="'.$_SERVER['PHP_SELF'].'?'.http_build_query($params+array('currentpage' => $i)).'">'.$i.'</a>';
}
Anpher