読者です 読者をやめる 読者になる 読者になる

俺の報告

RoomClipを運営するエンジニアの日報(多分)です。

PHPで手軽にページネーション サンプルコード - 日報 #123

ページネーションって面倒ですよね。
きっとよいプラクティスがあるはずですし、
色んなフレームワークに既に入っているものかと思います。

ですが、毎度毎度自分で書いている気がしますのは何故でしょうか。
なんか要求と合わない実装が多いんですよね、、、
php pagination exampleでぐぐってもなんだかなぁという感じでした。 一応今回ボクがつくった簡単なページネーションfunctionを置いておきますが、
恐らくこれも誰にも役にたたないのでしょう。

でも置くだけ置いておきます。

<?php

// こんな感じで使う
// 全体で20ページ、表示させたいページの数は5、今のページは4、最初のページは1
$page_info = display_paging(4, 5, 20, 1);
var_dump($page_info);
// array(min_page=>1, prev_page=>3, next_page=>5, max_page=>20, display_pages=>array(2,3,4,5,6))
// という配列が返ってくる

// ちなみに、左端、右端に到達している時、max_pageやprev_pageなどは消失するため、NULLが代入される

if (!function_exists('display_paging')) {
     /**
      * In paging processes, If you need to show like below,
      * 1... prev 6 7 8 9 10 next ...100
      * Use this function.
      * Return array('min_page', 'prev_page', 'display_pages'=>array(), 'next_page', 'max_page')
      *
      * The patterns are... ($page_range = 5)
      *
      * 1...6 7 8 9 10...100: [1, 7, [6,7,8,9,10], 9, 100]
      * 1 2 3 4 5 ...100: [null, 2, [1,2,3,4,5], 4, 100]
      * 1 2 3 4 5: [null, 2, [1,2,3,4,5], 4, null]
      * 1 2 : [null, null, [1,2], 2, null]
      * 1...6 7 8 9 10 : [null, 8, [6.7.8.9.10], 10, null]
      *
      * @param int $start_page     current page number
      * @param int $page_range     page range for displaying
      * @param int $max_page     max page number
      * @param int $min_page     min page number | default value is 1
      * @return array
      */
     function display_paging ($start_page, $page_range, $max_page, $min_page=1)
     {
          // args must be int
          $start_page = intval($start_page);
          $page_range = intval($page_range);
          $max_page   = intval($max_page);
          $min_page   = intval($min_page);

          // not zero
          if (($start_page * $page_range * $max_page * $min_page) === 0)
               return array();

          // $page_range must be odd number, and not 1
          if ($page_range % 2 === 0 || $page_range === 1)
               return array();
         
          $result = array();
         
          $fair_range_min = $start_page - ($page_range - 1) / 2;
          $fair_range_max = $start_page + ($page_range - 1) / 2;
         
          // Left adjust
          if ($fair_range_min <= $min_page) {
               $result['min_page'] = NULL;
               $fair_range_max = $fair_range_max + ($min_page - $fair_range_min);
               $fair_range_min = $min_page;
          } else {
               $result['min_page'] = $min_page;
          }
         
          // Right adjust
          if ($fair_range_max >= $max_page) {
               $result['max_page'] = NULL;
               $fair_range_min = $fair_range_min - ($fair_range_max - $max_page);
               $fair_range_max = $max_page;
               if ($fair_range_min < $min_page)
                    $fair_range_min = $min_page;
          } else {
               $result['max_page'] = $max_page;
          }
         
          // create array
          for ($i=$fair_range_min; $i <= $fair_range_max; $i++) {
               // prev page
               if ($i === $start_page) {
                    $result['prev_page'] = ($start_page - 1) < $min_page ? NULL : ($start_page - 1);
               }
               // next page
               if ($i === $start_page) {
                    $result['next_page'] = ($start_page + 1) > $max_page ? NULL : ($start_page + 1);
               }
               if ($i > 0 && $i >= $min_page && $i <= $max_page)
                    $result['display_pages'][] = $i;
          }
          return $result;
     }
}
?>

まぁ、、、
どなたかの参考になれば、、、
それでは。