Skip to content

Instantly share code, notes, and snippets.

@Tenderfeel
Last active September 17, 2019 03:40
Show Gist options
  • Save Tenderfeel/9134f68a5468b33c98deccb043e4bc65 to your computer and use it in GitHub Desktop.
Save Tenderfeel/9134f68a5468b33c98deccb043e4bc65 to your computer and use it in GitHub Desktop.
<?php
// 7.0 厳密な型宣言(strictモード)
declare(strict_types = 1);
namespace pagination; // 名前空間
/**
* ダミーデータ
* @namespace pagination
*/
class DataList {
/**
* データの入れ物
* @type {array}
*/
private $data = [];
// private array $data; // 7.4 プロパティ型指定
/**
* constructor
* @param int $length データの総数 (7.0 スカラー型宣言)
*/
public function __construct(int $length = 53) {
// 指定された長さのデータ生成
$this->create($length);
}
/**
* データ総数のゲッター
* @return int (7.0 戻り値の型宣言)
*/
public function getCount(): int {
return count($this->data);
}
/**
* 1ページあたりの件数から総ページ数を算出
* @param int $perPage 1ページあたりのデータ件数
* @return int
*/
public function getTotalPage(int $perPage): int {
return (int) ceil($this->getCount() / $perPage);
}
/**
* データ生成
* @param int $length データの総数
*/
private function create(int $length = 53): void {
foreach(array_fill(0, $length, null) as $k => $v) {
$this->data[] = 'Item ' . ($k + 1);
}
}
/**
* 指定したページに該当するデータを返す
* @param int $page ページ番号
* @param int $perPage 1ページあたりの件数
*/
public function filter(int $page, int $perPage): array {
return array_filter($this->data, function($i) use ($page, $perPage) {
return $i >= ($page - 1) * $perPage && $i < $page * $perPage;
}, ARRAY_FILTER_USE_KEY);
// 7.4のアロー関数
// return array_filter($this->data, fn($i) => $i >= $page - 1 * $perPage && $i < $page * $perPage, ARRAY_FILTER_USE_KEY);
}
}
<?php
namespace website; //名前空間
include 'DataList.php';
include 'PaginationNavs.php';
include 'Pagination.php';
include 'PrevNext.php';
include 'PrevNext2.php';
include 'Numbers.php';
// 名前空間にクラスをインポート
use pagination\DataList as DataList;
use pagination\PrevNext as PrevNext;
use pagination\PrevNext2 as PrevNext2;
use pagination\Numbers as Numbers;
$dataList = new DataList(54); //ダミーデータインスタンス生成
$page = $_GET['page'] ?? 1; // 現在のページ(7.0 Null合体演算子)
$page = is_int($page) ? $page : 1; // 数値以外なら数字にする圧
$perPage = 5; // 1ページあたりのデータ件数
$count = $dataList->getCount(); // データの総数
$totalPage = $dataList->getTotalPage($perPage); // 最大ページ数
print "<pre>page:" . $page . "\n";
print "count:" . $count . "\n";
print "perPage:". $perPage . "\n";
print "totalPage:" . $totalPage . "</pre>";
?>
<div>
<?php PrevNext::print($page, $totalPage); ?>
</div>
<div>
<?php
$prevNext2 = new PrevNext2($page, $totalPage);
$prevNext2->print($page, $totalPage); ?>
</div>
<div>
<?php
$numbersLink = new Numbers($page, $totalPage);
$numbersLink->print();
?>
</div>
<?php
declare(strict_types = 1);
namespace pagination; // 名前空間
/**
* ページ番号リンクを表示するナビゲーション
*/
class Numbers extends Pagination {
/**
* $pageの前後に表示するページ番号の数
* @type int
*/
protected $pageRange = 2;
/**
* ページ番号格納する配列
* @ type array
*/
protected $nums = [];
/**
* ページ番号リンクの始点
* @type int
*/
protected $start = 1;
/**
* ページ番号リンクの終点
* @type int
*/
protected $end;
/**
* constructor
* @param int $totalPage データの最大件数
* @param int $page 現在のページ番号
* @param int $pageRange $pageから前後何件のページ番号を表示するか
*/
public function __construct(int $page = 1, int $totalPage, int $pageRange = 2) {
parent::__construct($page, $totalPage, $pageRange);
$this->pageRange = $pageRange;
}
/**
* 必要な数値を算出
* @override
*/
protected function calc(): void {
parent::calc();
$this->start = max($this->page - $this->pageRange, 2); // ページ番号始点
$this->end = min($this->page + $this->pageRange, $this->totalPage - 1); // ページ番号終点
if ($this->page === 1) { // 1ページ目の場合
$this->end = $this->pageRange * 2; // 終点再計算
}
// ページ番号格納
for ($i = $this->start; $i <= $this->end; $i++) {
$this->nums[] = $i;
}
}
/**
* 現在地が中央に来る省略つきページ番号リンク出力
* @param int $page 現在のページ番号
* @param array $nums ページ番号の配列
*/
public function truncateNums(): void {
// 最初のページ番号へのリンク
print '<a href="?page=' . $this->startPage . '">' . $this->startPage . '</a>';
if ($this->start > $this->pageRange) print "..."; // ドットの表示
foreach ($this->nums as $num) {
// 現在地
if ($num === $this->page) {
print '<span class="current">' . $num . '</span>';
} else {
// ページ番号リンク表示
print '<a href="?page='. $num .'" class="num">' . $num . '</a>';
}
}
if (($this->totalPage - 1) > $this->end ) print "..."; //ドットの表示
//最後のページ番号へのリンク
if ($this->page < $this->totalPage) {
print '<a href="?page='. $this->totalPage .'">' . $this->totalPage . '</a>';
} else {
print "<span>${$this->totalPage}</span>"; // ダブルクォーテーションなら
}
}
/**
* ページナビゲーション出力
* @abstract
*/
public function print(): void {
$this->firstPage();
$this->prevPage();
$this->truncateNums();
$this->nextPage();
$this->lastPage();
}
}
<?php
declare(strict_types = 1);
namespace pagination;
/**
* ページナビゲーションインターフェース
*/
interface PaginationInterface {
// ナビゲーションを出力するメソッド
public function print();
public function firstPage();
public function lastPage();
public function prevPage();
public function nextPage();
}
/**
* ページナビゲーション抽象クラス
*/
abstract class Pagination implements PaginationInterface {
use PaginationNavs; // トレイト
/**
* 現在のページ番号
* @type int
*/
protected $page = 1;
/**
* ページ総数
* @type int
*/
protected $totalPage;
/**
* 最初のページ
*/
protected $startPage = 1;
/**
* 前のページ番号
* @type int
*/
protected $prev;
/**
* 次のページ番号
* @type int
*/
protected $next;
/**
* constructor
* @param int $totalPage データの最大件数
* @param int $page 現在のページ番号
* @param int $pageRange $pageから前後何件のページ番号を表示するか
*/
public function __construct(int $page = 1, int $totalPage) {
$this->totalPage = $totalPage;
$this->page = $page; // ページ番号
$this->calc();
}
/**
* 必要な数値を算出
*/
protected function calc(): void {
// 前ページと次ページの番号計算
$this->prev = max($this->page - 1, 1);
$this->next = min($this->page + 1, $this->totalPage);
}
/**
* 前のページへのリンク
* @abstract
*/
public function prevPage(): void {
self::prev($this->page, 1);
}
/**
* 次のページへのリンク
* @abstract
*/
public function nextPage(): void {
self::next($this->page, $this->totalPage);
}
/**
* 最初のページへのリンク表示
* @abstract
*/
public function firstPage(): void {
if ($this->page > 1 && $this->page !== 1){
print '<a href="?page=1" title="最初のページへ">« 最初へ</a>';
} else {
print '<span>« 最初へ</span>';
}
}
/**
* 最後のページへのリンク表示
* @abstract
*/
public function lastPage(): void {
if ($this->page < $this->totalPage){
print '<a href="?page=' . $this->totalPage . ' title="最後のページへへ">最後へ »</a>';
} else {
print '<span>最後へ »</span>';
}
}
}
<?php
declare(strict_types = 1);
namespace pagination;
/**
* ページナビゲーションのトレイト
*/
trait PaginationNavs {
/**
* 前のページへのリンク出力
* @param int $page 現在のページ番号
* @param int $startPage 最初のページ番号
*/
static function prev(int $page, int $startPage = 1): void {
$prev = max($page - 1, $startPage); // 前のページ番号
if ($page != 1) { // 最初のページ以外
print '<a href="?page=' . $prev . '">&laquo; 前へ</a>';
} else {
print '<span>&laquo; 前へ</span>';
}
}
/**
* 次のページへのリンク出力
* @param int $page 現在のページ番号
* @param int $totalPage 総ページ数
*/
static function next(int $page, int $totalPage): void {
$next = min($page + 1, $totalPage); // 次のページ番号
if ($page < $totalPage){ // 最後のページ以外
print '<a href="?page=' . $next . '">次へ &raquo;</a>';
} else {
print '<span>次へ &raquo;</span>';
}
}
}
<?php
declare(strict_types = 1);
namespace pagination; // 名前空間
/**
* 前後へのページにリンクするナビゲーション
* @namespace pagination
*/
class PrevNext {
use PaginationNavs; // トレイト
/**
* ナビゲーションの出力
* @param int $totalPage 総ページ数
* @param int $page 現在のページ番号
*/
static function print(int $page = 1, int $totalPage): void {
self::prev($page, 1);
self::next($page, $totalPage);
}
}
<?php
declare(strict_types = 1);
namespace pagination;
/**
* 前後ページヘのナビゲーション
* 総ページ数表示つき
*/
class PrevNext2 extends Pagination {
/**
* constructor
* @param int $totalPage データの最大件数
* @param int $page 現在のページ番号
*/
public function __construct(int $page = 1, int $totalPage) {
parent::__construct($page, $totalPage);
}
/**
* 総ページ数の表示
*/
public function totalPage(): void {
print '<span class="totalPage">' . $this->page . '/' . $this->totalPage . '</span>';
}
/**
* ページネーション出力
* @abstract
*/
public function print(): void {
$this->firstPage();
$this->prevPage();
$this->totalPage();
$this->nextPage();
$this->lastPage();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment