像谷歌一样分页的逻辑

Tho*_*asK 32 php oop pagination class paginate

谷歌的分页行为背后的逻辑是什么?

我的分页器是这样的:

[1]  2   3  ...  184   >
 <   1  [2]  3   4  ...  184   >
 <   1   2  [3]  4   5  ...  184   >
 <   1   2   3  [4]  5   6   ...  184   >
 <   1  ...  3   4  [5]  6    7   ...  184   >
 <   1  ...  4   5  [6]  7    8   ...  184   >
 <   1  ...  5   6  [7]  8    9   ...  184   >
 <   1  ...  6   7  [8]  9    10  ...  184   >
Run Code Online (Sandbox Code Playgroud)

以下是上述示例的实时版本:http://www.dev.thomaskile.me/?page = test-zone&modules = Pepinator.
我知道为什么会这样; 我已将当前页面每一侧显示的页码数量设置为两(2).

我宁愿让数字范围像这样:

[1]  2   3   4   5   6   7   8   ...   184   >
 <   1  [2]  3   4   5   6   7   ...   184   >
 <   1   2  [3]  4   5   6   7   ...   184   >
 <   1   2   3  [4]  5   6   7   ...   184   >
 <   1  ...  3   4  [5]  6   7   ...   184   >
 <   1  ...  4   5  [6]  7   8   ...   184   >
 <   1  ...  5   6  [7]  8   9   ...   184   >    
 <   1  ...  6   7  [8]  9   10  ...   184   >
Run Code Online (Sandbox Code Playgroud)

它是在开始和结束时我需要做出一些改变,但无法弄清楚如何使它变得简单操作......
我也想让它变得灵活.意思是我希望能够改变每一侧所需页面的数量,并让脚本扩展并计算所有...

到目前为止,这是我的代码:

/**
 *  page controller buttons 
 *  @param str $this->querySting      href="URL string"
 *  @param str $this->pageIdentifier  $_GET['this-name']
 *  @param int $this->numPages        Total amount of pages
 *  @param int $this->midRange        Number of pages to show on each side of current page
 */

public function prevPage() 
{
    if ($this->currentPage > 1){ 
        $prevPage = ($this->currentPage - 1); 
        return '<a href="'.$this->queryString.'&'.$this->pageIdentifier.'='.$prevPage.'" class="prev">prev</a>'; 
    }
}
public function nextPage() 
{
    if ($this->currentPage < $this->numPages) { 
        $nextPage = $this->currentPage + 1;
        return '<a href="'.$this->queryString.'&'.$this->pageIdentifier.'='.$nextPage.'" class="next">next</a>';  
    }  
}
public function firstPage() 
{
    if ($this->currentPage > ($this->midRange + 1)) {  //  if number of pages between "currentPage" and "firstPage" exceeds $midRange with 1...
        $firstPage .= '<a href="'.$this->queryString.'&'.$this->pageIdentifier.'=1" class="first">1</a>';  //  ...show "first page"-link
        if ($this->currentPage > ($this->midRange + 2)) {   //  if number of pages between $currentPage and "first page" exceeds $midRange with more than 1
            $firstPage .= '&hellip;';  //  add "..." between "1st page"-link and first page in $range
        }
    }
    return $firstPage;
}
public function lastPage() 
{
    if ($this->currentPage < ($this->numPages - $this->midRange)) {  //  if number of pages between "currentPage" and "last page" is equal to $midRange
        if (($this->currentPage < ($this->numPages - $this->midRange) - 1)) {  //  if number of pages between $currentPage and "last page" exceeds $range with more than two
            $lastPage .= '&hellip;';  //  add "..." between "last page"-link and last page in $range
        } 
        $lastPage .= '<a href="'.$this->queryString.'&'.$this->pageIdentifier.'='.$this->numPages.'" class="last">'.$this->numPages.'</a>';   //  show "last page"-link
    }
    return $lastPage;
}

#  Range of pages between (prev first ...) and (... last next)
public function listPages() 
{
    for ($i = ($this->currentPage - $this->midRange); $i < (($this->currentPage + $this->midRange) + 1); $i++){
       if (($i > 0) && ($i <= $this->numPages))  //  if page number are within page range
       {
          if ($i == $this->currentPage) { $listPages .= '<a class="current">'.$i.'</a>'; }  //  if we're on current page
          else { $listPages .= '<a href="'.$this->queryString.'&'.$this->pageIdentifier.'='.$i.'">'.$i.'</a>'; }  //  if not current page
        }
    }
    return $listPages; 
}
Run Code Online (Sandbox Code Playgroud)

inv*_*sal 40

这就是我为我的分页做的事情.

$startPage = $currentPage - 4;
$endPage = $currentPage + 4;

if ($startPage <= 0) {
    $endPage -= ($startPage - 1);
    $startPage = 1;
}

if ($endPage > $totalPage)
    $endPage = $totalPage;

if ($startPage > 1) echo " First ... ";
for($i=$startPage; $i<=$endPage; $i++) echo " {$i} ";
if ($endPage < $totalPage) echo " ... Last ";
Run Code Online (Sandbox Code Playgroud)

我相信我的代码是自我解释的,但我会尝试用简单的英语解释它.首先,在生成分页之前,您需要先了解两件事:$ totalPage$ currentPage.

第1步:假设当前页面处于中间范围.$ startPage和$ endPage存储分页尝试生成的页面范围.

第2步:如果$ startPage为负数,那么你需要化妆$ endPage.

第3步:如果$ endPage超过$ totalPage,则$ endPage是最后一页.

第4步:将分页生成为HTML.(这取决于你希望你的分页看起来如何.我将简单地使用纯文本来表示我的分页)

if ($startPage > 1) echo " First ... ";
for($i=$startPage; $i<=$endPage; $i++) echo " {$i} ";
if ($endPage < $totalPage) echo " ... Last ";
Run Code Online (Sandbox Code Playgroud)

修复了我之前逻辑的缺陷

$startPage = ($curPage < 5)? 1 : $curPage - 4;
$endPage = 8 + $startPage;
$endPage = ($totalPage < $endPage) ? $totalPage : $endPage;
$diff = $startPage - $endPage + 8;
$startPage -= ($startPage - $diff > 0) ? $diff : 0;

if ($startPage > 1) echo " First ... ";
for($i=$startPage; $i<=$endPage; $i++) echo " {$i} ";
if ($endPage < $totalPage) echo " ... Last ";
Run Code Online (Sandbox Code Playgroud)


Aut*_*ard 5

这次谈话对我来说是一个很好的开始!但我希望分页符更接近原始问题的意图,即:
1)可以包含在具有变量的函数中,以改变当前要显示的当前页面和当前页面的页面数量.
2)保持恒定的宽度,类似于原始帖子:

 <  [1]   2    3    4    5    6   7    ...   99   >
 <   1   [2]   3    4    5    6   7    ...   99   >
 <   1    2   [3]   4    5    6   7    ...   99   >
 <   1    2    3   [4]   5    6   7    ...   99   >
 <   1    2    3    4   [5]   6   7    ...   99   >
 <   1   ...   4    5   [6]   7   8    ...   99   >
 <   1   ...   5    6   [7]   8   9    ...   99   >
 <   1   ...   92   93  [94]  95  96   ...   99   >
 <   1   ...   93   94  [95]  96  97   98    99   >
 <   1   ...   93   94   95  [96] 97   98    99   >
 <   1   ...   93   94   95   96 [97]  98    99   >
 <   1   ...   93   94   95   96  97  [98]   99   >
 <   1   ...   93   94   95   96  97   98   [99]  >
Run Code Online (Sandbox Code Playgroud)

3)在你有1 ... 3的情况下继续显示数字"2"而不是"..."
4)结束时同样的事情.

所以这就是我做的.我使用不同的语言(coffeescript)进行编码,但无论如何它应该起到良好的sudo-code的作用:

get_pages_array = (total_page, each_side, curr_page) ->
    if total_page <= (2*each_side)+5
        # in this case, too few pages, so display them all
        start_page = 1
        end_page = total_page
    else if curr_page<=each_side+3
        # in this case, curr_page is too close to the beginning
        start_page = 1
        end_page = (2*each_side)+3
    else if curr_page >= total_page - (each_side+2)
        # in this case, curr_page is too close to the end
        start_page = total_page - (2*each_side) - 2
        end_page = total_page
    else
        # regular case
        start_page = curr_page - each_side
        end_page = curr_page + each_side
    return_me = []
    if start_page> 1
        return_me.push "1"
    if start_page>2
        return_me.push "..."
    for x in [start_page..end_page]
        return_me.push x
    if end_page<total_page-1
        return_me.push "..."
    if end_page<total_page
        return_me.push total_page
    return return_me
Run Code Online (Sandbox Code Playgroud)

我在each_side = 2上使用这个代码,所以我确定它的工作原理.

编辑:根据@Vextil修复逻辑