SitePoint Sponsor

User Tag List

Results 1 to 2 of 2
  1. #1
    SitePoint Guru risoknop's Avatar
    Join Date
    Feb 2008
    Location
    end($world)
    Posts
    834
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Refactoring pagination class

    PHP Code:
    <?php

    /*
     @desc Paginates content
     @author Richard Knop
    */
    class Paginator
    {
        public 
    $numberOfItems;
        
        public 
    $maxPerPage;
        
        public 
    $currentPage;
        
        private 
    $lastPage;
        
        public 
    $firstLinkAnchor '<<';
            
        public 
    $prevLinkAnchor '<';
        
        public 
    $nextLinkAnchor '>';
        
        public 
    $lastLinkAnchor '>>';

        
    /*
         @desc Calculate last page (i.e. number of pages)
         @access public
         @param int $numberOfItems
         @param int $maxPerPage
         @return void
        */
        
    public function __construct($numberOfItems$maxPerPage)
        {
            
    $this->numberOfItems $numberOfItems;
            
    $this->maxPerPage $maxPerPage;
            
    $this->lastPage ceil($numberOfItems $maxPerPage);
        }
        
        
    /*
         @desc Set current page
         @access public
         @param int $currentPage
         @return void
        */
        
    public function setCurrentPage($currentPage)
        {
            
    $this->currentPage = ($currentPage >= && $currentPage <= $this->lastPage) ? $currentPage 1;
        }
        
        
    /*
         @desc Get limit clause for use in SQL query
         @access public
         @return string
        */
        
    public function getLimit()
        {
            return (
    $this->currentPage 1) * $this->maxPerPage.', '.$this->maxPerPage;
        }
        
        
    /*
         @desc Get array of page links
         @access public
         @param int $maxPageLinks
         @return array
        */
        
    public function getPageLinks($maxPageLinks)
        {
            if (
    $this->numberOfItems <= $this->maxPerPage)
            {
                return 
    false;
            }
            
            
    $maxPageLinks = ($maxPageLinks >= $this->lastPage) ? $this->lastPage $maxPageLinks;
            if (
    $this->currentPage == 1)
            {
                for (
    $i 1$i <= $maxPageLinks 1$i++)
                {
                    
    $pageLinks[$i] = $i;
                }
                
                
    $pageLinks[$this->nextLinkAnchor] = $this->currentPage 1;
                
    $pageLinks[$this->lastLinkAnchor] = $this->lastPage;
                
                return 
    $pageLinks;
            }
            else if (
    $this->currentPage == $this->lastPage)
            {
                
    $pageLinks[$this->firstLinkAnchor] = 1;
                
    $pageLinks[$this->prevLinkAnchor] = $this->currentPage 1;
                
                for (
    $i $this->lastPage $maxPageLinks$i <= $this->lastPage$i++)
                {
                    
    $pageLinks[$i] = $i;
                }
                
                return 
    $pageLinks;
            }
            else
            {
                
    $pageLinks[$this->firstLinkAnchor] = 1;
                
    $pageLinks[$this->prevLinkAnchor] = $this->currentPage 1;
                
                
    $j = ($this->currentPage $maxPageLinks 1) ? $this->currentPage $maxPageLinks;
                for (
    $i $this->currentPage $j$i <= $this->currentPage$i++)
                {
                    
    $pageLinks[$i] = $i;
                }
                
                
    $j = ($this->currentPage $maxPageLinks $this->lastPage) ? $this->lastPage $this->currentPage $maxPageLinks;
                for (
    $i $this->currentPage 1$i <= $this->currentPage $j$i++)
                {
                    
    $pageLinks[$i] = $i;
                }
                
                
    $pageLinks[$this->nextLinkAnchor] = $this->currentPage 1;
                
    $pageLinks[$this->lastLinkAnchor] = $this->lastPage;
                
                return 
    $pageLinks;
            }
        }
    }
    As I understand it (correct me if I am wrong) - a flexible pagination class should just calculate the number of pages and build an array of page links. It shouldn't make any connections to database or display any data nor should it do any other additional tasks.

    This is what I have attempted to do in the above class but I am little bit confused about a way how to mark the current page when building the array with page links... Array has already two dimensions so adding another dimension is probably way over complicated. Should I just do that outside the class?

  2. #2
    $books++ == true matsko's Avatar
    Join Date
    Sep 2004
    Location
    Toronto
    Posts
    795
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I've had the same issue as you in the past:

    depending on what I am indexing, I use an interface.

    This is what I have now:

    This Indexing class is only used for Indexing database results:

    PHP Code:
    interface Indexable {

        public function 
    getTotal();
        public function 
    getLimit();
        public function 
    start($mins);
        public function 
    getEmptyRow($t,$i);
        public function 
    getRow($row,$t,$i);
        public function 
    getEmptyResult($t);
        public function 
    fixEmptyResultTotals();

    }

    class 
    Index {

        
    //constants
        
    const DEFAULT_LIMIT 30;

        
    /**
         * @var boolean
         */
        
    protected $showEmpty;

        
    /**
         * @var boolean
         */
        
    protected $completeLoop;

        
    /**
         * @var string
         */
        
    protected $baseLink;

        
    /**
         * @var Indexable
         */
        
    protected $object;

        
    /**
         * @var int
         */
        
    protected $total;

        
    /**
         * @var int
         */
        
    protected $limit;

        
    /**
         * @var int
         */
        
    protected $minValue;

        
    /**
         * @var int
         */
        
    protected $maxValue;

        
    /**
         * @var int
         */
        
    protected $currentPage 1;

        
    /**
         * @var int
         */
        
    protected $totalPages 1;

        
    /**
        * @returns array the default options for the object
        */
        
    protected function _getOptions() {
            return array(
                
    'completeLoop'         => false,
                
    'showEmptyResult'     => true
                
    'getIndex'            => 'page_num',
                
    'baseLink'            => './'
            
    );
        }

        
    /**
        * @param Indexable $object the object that will be indexed
        * @see Indexable
        * @param array $options the options values that will be applied to the object
        */
        
    public function __construct(Indexable $object,array $options null) {

            
    //set options
            
    $options array_merge($this->_getOptions(),$options);

            
    //the object contains the properties
            
    if(isset($options['limit'])) {
                
    $this->limit = (int)$options['limit'];
            }
            else {
                
    $this->limit $object->getLimit();
                if(
    $this->limit<=0)
                
    $this->limit self::DEFAULT_LIMIT;
            }

            
    //check the rest of the options
            
    $this->showEmpty    $options['showEmptyResult'];
            
    $this->completeLoop    $options['completeLoop'];
            
    $this->getIndex     $options['getIndex'];
            
    $this->baseLink     $options['baseLink'];
            
    $this->object        $object;

            
    //get the current page
            
    if(isset($_GET[$this->getIndex])&&!empty($_GET[$this->getIndex]))
            
    $this->currentPage = (int)$_GET[$this->getIndex];
            if(
    $this->currentPage<1)
            
    $this->currentPage 1;

            
    //if there are no values for the object, then no index calculations are required
            
    $total = (int)$object->getTotal();
            if(!
    $total||$total<=0) return; //no point

            //set total
            
    $this->total $total;

            
    //calculate the index
            
    $this->_calculateIndex();
        }

        private function 
    _calculateIndex() {
            
    //the total pages is required
            
    if($this->total>$this->limit) {
                
    $this->totalPages ceil($this->total/$this->limit);
                if(
    $this->currentPage $this->totalPages)
                
    $this->currentPage 1;

                
    $this->minValue $this->currentPage*$this->limit-$this->limit;
                
    $this->maxValue min($this->minValue+$this->total,$this->limit);

                
    //this will determine the results according to what the current page is
                
    $this->mins $this->limit;
                if(
    $this->limit>$this->total)
                
    $this->mins $this->total;
                elseif(
    $this->totalPages>1&&$this->currentPage>1&&$this->minValue>0)
                
    $this->mins $this->minValue.','.$this->limit;
            }
            else {
                
    $this->mins $this->total;
                
    $this->minValue 1;
                
    $this->maxValue $this->total;
            }
        }

        
    /**
        * @returns int
        */
        
    public function getTotalPages() {
            return 
    $this->totalPages;
        }

        public function 
    changePage($pageNumber=1) {
            if(
    $pageNumber <= $this->totalPages && $pageNumber != $this->currentPage) {
                
    $this->currentPage $pageNumber;
                
    $this->_calculateIndex();
            }
        }

        public function 
    changeToFirstPage() {
            
    $this->changePage(1);
        }

        public function 
    changeToLastPage() {
            
    $this->changePage($this->totalPages);
        }

        
    /**
        * @returns array an array containing the min and max values
        */
        
    public function getMinAndMax() {
            return array(
                
    'min' => $this->minValue,
                
    'max' => $this->maxvalue
            
    );
        }

        
    /**
        * displays the contents of the object with its set indexing
        * @param string $tab the HTML tab amount
        * @returns void
        */
        
    public function show($tab='    ') {
            
    //Start
            
    $query null;
            if(
    $this->total>0)
            
    $query $this->object->start($this->mins);

            
    //Check Rows
            
    if($this->total==0||!$query) {

                
    //show empty
                
    if($this->showEmpty) {
                    echo 
    $this->object->getEmptyResult($tab);
                }

                
    //stop
                
    return;
            }

            
    //Set Vars
            
    $data '';
            
    $fetch true;
            
    $hasFetched false;

            
    //Start Fetching Contents
            
    for($i=1;$i<=$this->limit;$i++) {

                
    //Fetch
                
    $row=$query->assoc();

                
    //Determine What todo with the row
                
    if($row) {
                    
    $hasFetched true;
                    
    $data .= $this->object->getRow($row,$tab,$i);
                }
                elseif(
    $this->completeLoop)
                
    $data .= $this->object->getEmptyRow($tab,$i);
                else
                break;
            }

            
    //Check Empty Nothing
            
    if(!$hasFetched)
            
    $this->object->fixEmptyResultTotals();

            
    //Show
            
    echo $data;
        }
    }

    class 
    IndexHTML extends Index {

        
    //Flags
        
    public $showFirstAndLastPages true;

        protected 
    $disabledLinks true;

        
    /**
        * displays the total amount of records
        * @returns void
        */
        
    public function showResultTotals($prefix='results') {
            
    //Check Results Found
            
    if($this->total>0) {
                
    //Check Limit
                
    if($this->limit>0&&$this->maxValue!=$this->total)
                echo 
    ' '.$prefix.': <em>'.($this->minValue+1).'</em> to <em>'.(min($this->maxValue*$this->currentPage,$this->total)).'</em> of <em>'.$this->total.'</em>';
                else
                echo 
    'total '.$prefix.': <em>'.$this->total.'</em>';
            }
            else
            echo 
    'no '.$prefix.' found';
        }

        
    /**
        * @returns array the default options for the object
        */
        
    protected function _getOptions() {

            
    //get the options
            
    $options parent::_getOptions();

            
    //extend
            
    $options['disabledLinks']=true;

            
    //super
            
    return $options;
        }

        
    /**
        * displays the total amount of pages and the current page
        * @returns string
        */
        
    public function showPageTotals() {
            
    //Check Pages
            
    $totalPages $this->totalPages;
            if(!isset(
    $totalPages)||$totalPages==0)
            
    $totalPages 1;

            
    //Check Current Page
            
    $page $this->currentPage;
            if(!
    $page||$page==0)
            
    $page 1;

            
    //this is the text that displays the current page in html format
            
    echo 'page: <em>'.$page.'</em> of <em>'.$totalPages.'</em>'."\n";
        }

        
    /**
        * disiplays the numbers in a "123 ... 9" format
        * @param string $t the HTML tab amount
        * @param int $totalNumbers the maximum total amount of number links at one time
        * @param string $baseLink the URL querystring
        * @returns void
        */
        
    public function showPageNumbers($t='   ',$totalNumbers=9,$baseLink=null)
        {
            
    //Set HTML
            
    $html $t.'<ol class="index">'."\n";

            
    //Must Be Even
            
    if($totalNumbers%2==0)
            
    $totalNumbers++;

            
    //check given baseLink
            
    if($baseLink===null)
            
    $baseLink=$this->baseLink;

            
    //Check Post
            
    if($baseLink[0]=="/")
            
    $baseLink substr($baseLink,1);

            
    //Set Vars
            
    $startPosition 1;
            
    $endPosition 1;
            
    $surroundingNumbers floor($totalNumbers/2);

            
    //Check Total
            
    if($totalNumbers>$this->totalPages && !$this->disabledLinks)
            
    $totalNumbers $this->totalPages;

            
    //these booleans will determine if the index has left and right arrows
            
    $allowNextPage $this->currentPage<$this->totalPages;
            
    $allowPrevPage $this->currentPage>1;

            
    //these values are for understanding the limits of the index
            
    $finalMiddleEndPosition $this->totalPages-$surroundingNumbers;
            
    $disabledIndex false;

            
    //Determine Start and End Numbers
            
    if($this->disabledLinks==true && $this->totalPages $surroundingNumbers) {
                
    $startPosition=1;
                
    $endPosition=$totalNumbers;
                
    $disabledIndex $this->totalPages+1;
            }
            elseif(
    $this->currentPage<=$surroundingNumbers||$this->totalPages<=$totalNumbers) { //the first numbers
                
    $startPosition=1;
                
    $endPosition=$totalNumbers;
            }
            elseif(
    $this->currentPage>=$finalMiddleEndPosition) { //the last numbers
                
    $startPosition $this->totalPages-$totalNumbers+1;
                
    $endPosition $this->totalPages;
            }
            else { 
    //somewhere in the middle
                
    $startPosition $this->currentPage-$surroundingNumbers;
                
    $endPosition $this->currentPage+$surroundingNumbers;
            }

            
    //Check Start
            
    if($allowPrevPage)
            
    $html .= $t.' <li class="prev-page" ><a href="/'.$baseLink.'/?p='.($this->currentPage-1).'">&lt;</a></li>'."\n";
            else
            
    $html .= $t.' <li class="prev-page disabled"><em>First Page</em></li>'."\n";

            
    //Loop Pages
            
    for($i=$startPosition;$i<=$endPosition;++$i)
            {
                if(
    $i==$this->currentPage)
                
    $html .= $t.' <li class="current-page"><em>'.$i.'</em></li>'."\n";
                else {
                    if(
    $disabledIndex && $i >= $disabledIndex)
                    
    $html .= $t.' <li><em class="disabled">'.$i.'</em></li>'."\n";
                    else
                    
    $html .= $t.' <li><a href="/'.$baseLink.'/?p='.$i.'">'.$i.'</a></li>'."\n";
                }
            }

            
    //Check Start
            
    if($allowNextPage)
            
    $html .= $t.' <li class="next-page"><a href="/'.$baseLink.'/?p='.($this->currentPage+1).'">&gt;</a></li>'."\n";
            else
            
    $html .= $t.' <li class="next-page disabled"><em>Last Page</em></li>'."\n";

            
    //Give the HTML
            
    echo $html.$t.'</ol>'."\n";
        }
    }


    ?> 
    I can't believe I ate the whole thing


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •