Jump to content

nesting prob in php pagination


rick.emmet

Recommended Posts

Hey Everyone,
I've been beating my head against the wall for two days on this one. I have a snippet of code that I have not touched for years – it used to run perfectly. I think I must have inadvertently changed the code at some point, and I can't get it to run properly.

It's a nesting problem in a series of “if  statements” and no matter what, I can't seem to nest these conditionals so they'll work. I'd like to use a switch statement, but I have five different arguments for it.

Here's the code:

$pagination = "";
if ($lastpage > 1) {
    $pagination .= "<div class=\"pagination\">";
    //previous button
    if ($page > 1) {
        // When the condition is met, the code below runs and then drops down to "echo $pagination;"
        $pagination.= "<a href=\"$targetpage?page=$prev\">< previous   </a>";
    } else {
        $pagination.= "<span class=\"disabled\">< previous</span>";

        //pages    
        if ($lastpage < 7 + ($adjacents * 2)) { //not enough pages to bother breaking it up
            for ($counter = 1; $counter <= $lastpage; $counter++) {
                if ($counter == $page) {
                    $pagination.= "<span class=\"current\"> $counter </span>";
                } else {
                    $pagination.= "<a href=\"$targetpage?page=$counter\"> $counter</a>";
                } // END OF FIRST SERIRES OF IF STATEMENTS
            }
        } elseif ($lastpage > 5 + ($adjacents * 2)) { //enough pages to hide some
            //close to beginning; only hide later pages
            if ($page < 1 + ($adjacents * 2)) {
                for ($counter = 1; $counter < 4 + ($adjacents * 2); $counter++) {
                    if ($counter == $page) {
                        $pagination.= "<span class=\"current\"> $counter </span>";
                    } else {
                        $pagination.= "<a href=\"$targetpage?page=$counter\"> $counter</a>";
                    }
                    $pagination.= "...";
                    $pagination.= "<a href=\"$targetpage?page=$lpm1\">$lpm1</a>";
                    $pagination.= "<a href=\"$targetpage?page=$lastpage\"> $lastpage</a>";
                }
                //in middle; hide some front and some back
            } elseif ($lastpage - ($adjacents * 2) > $page && $page > ($adjacents * 2)) {
                $pagination.= "<a href=\"$targetpage?page=1\">1</a>";
                $pagination.= "<a href=\"$targetpage?page=2\">2 </a>";
                $pagination.= "...";
                for ($counter = $page - $adjacents; $counter <= $page + $adjacents; $counter++) {
                    if ($counter == $page) {
                        $pagination.= "<span class=\"current\"> $counter </span>";
                    } else {
                        $pagination.= "<a href=\"$targetpage?page=$counter\"> $counter</a>";
                    }
                }
                $pagination.= "...";
                $pagination.= "<a href=\"$targetpage?page=$lpm1\">$lpm1</a>";
                $pagination.= "<a href=\"$targetpage?page=$lastpage\"> $lastpage</a>";

                //close to end; only hide early pages
            } else {
                $pagination.= "<a href=\"$targetpage?page=1\">1</a>";
                $pagination.= "<a href=\"$targetpage?page=2\">2 </a>";
                $pagination.= "...";
                for ($counter = $lastpage - (2 + ($adjacents * 2)); $counter <= $lastpage; $counter++) {
                    if ($counter == $page) {
                        $pagination.= "<span class=\"current\"> $counter </span>";
                    } else {
                        $pagination.= "<a href=\"$targetpage?page=$counter\"> $counter</a>";
                    }
                }
            }
        }

        //next button
        if ($page < $counter - 1) {
            $pagination.= "<a href=\"$targetpage?page=$next\">   next ></a>";
        } else {
            $pagination.= "<span class=\"disabled\">next ></span>";
            $pagination.= "</div>\n";
        }
    }
}
echo $pagination;

My “do-while” loop (below the pagination) creates a set of small tables that display information for each record. On page 1, everything looks fine. On any other page, the pagination only displays the “previous” link. Once the condition “if ($page > 1)” is met the next line is executed, echoing the “previous” link, and the code drops to the bottom of the function. I've tried every other kind of logic I can think of and am all out of ideas. BTW, I'm using procedural PHP on this project. Any help will be very appreciated.

 

Link to comment
Share on other sites

Somewhat rambling post:

 

On any other page, the pagination only displays the “previous” link.

Right. Because the code explicitly says "if after page 1 then show previous link else show a lot of stuff". If the code was working fine before then you made some pretty substantial changes to break it.

 

A lot of those ifs need to be separate from the others. The order goes:

1. Previous link

2. First couple pages if you want to show them

3. Middle pages

4. Last couple pages if you want to show them

5. Next link

None of those decisions should impact any of the others. Yes, there's some overlap, but keeping the logic separate (and a little duplicated) makes life much easier.

 

Ignoring the trivial previous and next links, there's a few ways of doing #2-4. My suggestions:

- Take the code you have now and set it aside for reference. Write the pagination stuff over again with a focus on making it simpler.

- If the first/last pages and middle pages overlap then use the middle pages to show them and constrain the first/last to not show

- Focus on making the middle pages show as much as possible, especially ensuring that the current page only shows up in this range. That means you can keep the logic for the current page's link in one place - don't need to duplicate everywhere that handles links.

- To do that, start off calculating the range of the middle pages and putting it into variables. The calculate the first pages' upper bound and last pages' lower bound accordingly and rely on the for loop to skip showing them.

- Use min() and max() to make your life easier

 

Done right you can get rid of the "close to beginning" and "close to end" stuff.

/* calculated first high, middle low, middle high, and last low before this point */

if (current page > 1) {
	show previous link
} else {
	show disabled previous link
}

for ($i = 1; $i <= first high; $i++) { // skips if first high was calculated <1
	show link
}

if (max(1, first high + 1) < middle low) {
	show gap
}

for ($i = middle low; $i <= middle high; $i++) {
	if ($i == current page) {
		show special link
	} else {
		show link
	}
}

if (middle high < min(last low - 1, last)) {
	show gap
}

for ($i = last low; $i <= last; $i++) { // skips if last low was calculated >last
	show link
}

if (current page < max page) {
	show next link
} else {
	show disabled next link
}
I tried to come up with better sample code but my brain just can't handle your "not enough pages" decisions right now. I think what you're aiming for is to not have a gap of one page (eg, 1 2 gap 4 5) but to show it and only start a gap for more than one (1 2 3 4 5 then 1 2 gap 5 6)? Calculate the variables like before but afterwards "stretch" the middle range to cover that gap, eg:

// calculate middle low and first high
if (middle low - first high <= 1) { // gap of 1
	middle low = first high + 1 // stretch to cover gap
}
(stretching the middle and not the first/last for the whole "make the middle pages show as much as possible" point)

 

 

Note: there may be a couple off-by-one errors in here.

Link to comment
Share on other sites

Hi Requinix,

Thank you so much for the reply! I spent all my time trying to find the correct way to nest this - I didn't even think about un-nesting it. I think this will work fine. BTW, I don't remember making any changes to this at all; this came from a tutorial or a posting on the forum (or a link from the forum). Looking at it now, its seems that it could not have ever worked as written. That really makes me wonder - how does one spell that sound Scooby Doo used to make when he was confused? Making something somewhat complicated into something very complicated doesn't usually work!!

 

Thanks again, I'll get right on it.

Cheers,

Rick

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.