phppaginationcontrollerdao

Pagination with Controllers -> keeps redirecting to index.php


I'm making a new thread on this, as I'm actually somewhere now.

I've got a paging system, but there's a problem.

I work with DAO's and controllers. Thing is, my second page (of my paging system) goes to index.php?page=2. The major problem here is that whenever you go to a page that doesn't exist in the index.php it redirects automatically to index.php. Page 2 isn't mentioned there as I can't mention every single page there as the pages will increase the more items there will be inserted.

Here's the entire code I'm using for the paging: (edited)

<?php

    $mysqli = new mysqli("localhost", "wanthave", "wanthavepass", "wanthave");      
    $count_mem = $mysqli->query("SELECT `id` FROM `wanthave_items`");
    $rows = $count_mem->num_rows;

    $perPage = 5; // items to be shown per page
    $num_pages = ceil($rows / $perPage);

    $visiblePages = 5; // if current page is 7 show: 5,6,7,8,9,...
    $visibleOffset = ceil($visiblePages / 2) - 1; // number of pages to show on the left and on the right of the current page



    // Where do you use this ???
    // $start = $page == 1 ? 0 : (($page - 1) * $perPage);

    if ($num_pages > 1) {

        $first = $last = $pagesStr = '';

            echo $first . $pageStr . $last;

        }
            foreach($items as $item) {
                echo "<li>
                    <a href=\"index.php?page=item-detail&id={$item['id']}\">{$item['name']}</a>
                </li>";
            }

            for ($n = 1; $n < ($num_pages + 1); $n++) {
                echo "<a href='index.php?page=$n'>$n</a>";        
                if ($n < $num_pages) echo ",&nbsp;";      
            }
?>

my index.php

<?php
session_start();

define('DS', DIRECTORY_SEPARATOR);
define('WWW_ROOT', __DIR__ . DS);

$routes = array(
    'home' => array(
        'controller' => 'Item',
        'action' => 'index'
    ),
    'register' => array(
        'controller' => 'Users',
        'action' => 'register'
    ),
    'login' => array(
        'controller' => 'Users',
        'action' => 'login'
    ),
    'logout' => array(
        'controller' => 'Users',
        'action' => 'logout'
    ),
    'item-detail' => array(
        'controller' => 'Item',
        'action' => 'detail'
    ),
);

if(empty($_GET['page'])) {
    $_GET['page'] = 'home';
}
if(empty($routes[$_GET['page']])) {
    header('Location: index.php');
    exit();
}

$route = $routes[$_GET['page']];
$controllerName = $route['controller'] . 'Controller';

require_once WWW_ROOT . 'controller' . DS . $controllerName . ".php";

$controllerObj = new $controllerName();
$controllerObj->route = $route;
$controllerObj->filter();
$controllerObj->render();

Solution

  • This is quite a good post on simple pagination with PHP Limit pagination page number

    With your example, for starter you should also validate that the page parameter is an integer and you can get partially rid of the very last if-else statement. So let's try optimizing the code a bit:

    <?php
    
        $mysqli = new mysqli("localhost", "wanthave", "wanthavepass", "wanthave");      
        $count_mem = $mysqli->query("SELECT `id` FROM `wanthave_items`");
        $rows = $count_mem->num_rows;
    
        $perPage = 5; // items to be shown per page
        $num_pages = ceil($rows / $perPage);
    
        $visiblePages = 5; // if current page is 7 show: 5,6,7,8,9,...
        $visibleOffset = ceil($visiblePages / 2) - 1; // number of pages to show on the left and on the right of the current page
    
        $page = isset($_REQUEST['page']) ? intval($_REQUEST['page']) : 1;    
    
        // Where do you use this ???
        // $start = $page == 1 ? 0 : (($page - 1) * $perPage);
    
        if ($num_pages > 1) {
    
            $first = $last = $pagesStr = '';
    
            if($num_pages > $visiblePages){ 
                // no need to show First page if already on it
                if($page != 1){
                    $first = "<a href='index.php?page=1'>First</a>";
                }
    
                // no need to show Last page if already on it
                if($page < $numPages){
                    $last = "<a href='index.php?page=$numPages'>Last</a>";
                }
    
                // the offset cannot be smaller or bigger than the min & max page number
                $fromPage = ($page - $visibleOffset) < 1 ? 1 : ($page - $visibleOffset);
                $toPage = ($page + $visibleOffset) > $numPage ? $numPage : ($page + $visibleOffset);
                for($i=$fromPage; $i<=$toPage; $i++){
                    $pagesStr .= "<a href='index.php?page=$i'>$i</a>";
                }
    
                echo $first . $pageStr . $last;
    
            } else {
    
                // NOTE: You don't really need this ELSE section at all
    
                // Where is $items defined ???
                foreach($items as $item) {
                    echo "<li>
                        <a href=\"index.php?page=item-detail&id={$item['id']}\">{$item['name']}</a>
                    </li>";
                }
    
                for ($n = 1; $n < ($num_pages + 1); $n++) {
                    echo "<a href='index.php?page=$n'>$n</a>";        
                    if ($n < $num_pages) echo ",&nbsp;";      
                }
         } 
    }
    ?>
    

    NOTE:

    If you choose to remove the ELSE seciton, make sure to remove the

    if($num_pages > $visiblePages){
        ...
    } 
    

    part as well. It's one unnecessary check less since you can simply use the $fromPage and $toPage to cycle all available pages.

    I haven't tried this code so there might be bugs in it, but the important thing is to not use hardcoded values anywhere in your code and to try and optimize the pagination process as much as possible (and there are few things that could be modified here).