SlideShare a Scribd company logo
Laravel の paginate は
一体何をやっているのか
第127回 PHP勉強会@東京
岡田 正平(おかだ しょうへい)@okashoi
• 株式会社ウィルゲート 2015年新卒入社
• 開発室 ソリューションユニット 所属
• PHP, Laravel, Vue.js
2
自己紹介
Slides:
① Laravel の paginate は何をやっているのか
• タイトル通り
② フレームワークのソースコードの追うときの思考プロセス
3
このスライドでつたえたい
https://laravel.com/docs/5.6/pagination
// Controller にて
$users = App¥User::paginate(15);
{{-- blade template にて --}}
<div class="container">
@foreach ($users as $user)
{{ $user->name }}
@endforeach
</div>
{{ $users->links() }}
// Controller にて
$users = App¥User::paginate(15);
{{-- blade template にて --}}
<div class="container">
@foreach ($users as $user)
{{ $user->name }}
@endforeach
</div>
{{ $users->links() }}
Laravel の paginate は一体何をやっているのか
routing を触らずに ページネーション用の URL (?page=x) が生まれる
• 勝手に routing が生成される?
だけでいい感じにページネーションのリンクが生まれる
8
なんか気持ち悪い……
$users->links()
……
// Controller にて
$users = App¥User::paginate(15);
{{-- blade template にて --}}
<div class="container">
@foreach ($users as $user)
{{ $user->name }}
@endforeach
</div>
{{ $users->links() }}
// Controller にて
$users = App¥User::paginate(15);
{{-- blade template にて --}}
<div class="container">
@foreach ($users as $user)
{{ $user->name }}
@endforeach
</div>
{{ $users->links() }}
• の戻り値
• ページネーションに必要な情報を持っている
• もこのクラスに生えている
12
¥Illuminate¥Pagination¥LengthAwarePaginator
// Controller にて
$users = App¥User::paginate(15);
¥Illuminate¥Database¥Query¥Builder::paginate()
links()
• の戻り値
• ページネーションに必要な情報を持っている
• もこのクラスに生えている
13
¥Illuminate¥Pagination¥LengthAwarePaginator
// Controller にて
$users = App¥User::paginate(15);
¥Illuminate¥Database¥Query¥Builder::paginate()
links()
14
¥Illuminate¥Pagination¥LengthAwarePaginator
// Controller にて
$users = App¥User::paginate(15);
これらの情報から、ページネーション部分の HTML を生成することはできる(わかる)
16
¥Illuminate¥Pagination¥LengthAwarePaginator
// Controller にて
$users = App¥User::paginate(15);
17
¥Illuminate¥Pagination¥LengthAwarePaginator
// Controller にて
$users = App¥User::paginate(15);
DBから取得できる
(わかる)
18
¥Illuminate¥Pagination¥LengthAwarePaginator
// Controller にて
$users = App¥User::paginate(15);
DBから取得できる
(わかる)
引数でもらう
(わかる)
19
¥Illuminate¥Pagination¥LengthAwarePaginator
// Controller にて
$users = App¥User::paginate(15);
DBから取得できる
(わかる)
引数でもらう
(わかる)
算出できる
(わかる)
20
¥Illuminate¥Pagination¥LengthAwarePaginator
// Controller にて
$users = App¥User::paginate(15);
DBから取得できる
(わかる)
引数でもらう
(わかる)
算出できる
(わかる)
??(わからない)
ここからは勘と執念の戦い
(なのでちょっと駆け足)
• の戻り値
• ページネーションに必要な情報を持っている
• もこのクラスに生えている
22
¥Illuminate¥Pagination¥LengthAwarePaginator
// Controller にて
$users = App¥User::paginate(15);
¥Illuminate¥Database¥Query¥Builder::paginate()
links()
23
¥Illuminate¥Database¥Query¥Builder::paginate()
public function paginate($perPage = 15, $columns = ['*'], $pageName = 'page', $page = null)
{
$page = $page ?: Paginator::resolveCurrentPage($pageName);
$total = $this->getCountForPagination($columns);
$results = $total ? $this->forPage($page, $perPage)->get($columns) : collect();
return $this->paginator($results, $total, $perPage, $page, [
'path' => Paginator::resolveCurrentPath(),
'pageName' => $pageName,
]);
}
24
¥Illuminate¥Database¥Query¥Builder::paginate()
public function paginate($perPage = 15, $columns = ['*'], $pageName = 'page', $page = null)
{
$page = $page ?: Paginator::resolveCurrentPage($pageName);
$total = $this->getCountForPagination($columns);
$results = $total ? $this->forPage($page, $perPage)->get($columns) : collect();
return $this->paginator($results, $total, $perPage, $page, [
'path' => Paginator::resolveCurrentPath(),
'pageName' => $pageName,
]);
}
currentPage を解決してそう
25
¥Illuminate¥Pagination¥AbstractPaginator
public static function resolveCurrentPage($pageName = 'page', $default = 1)
{
if (isset(static::$currentPageResolver)) {
return call_user_func(static::$currentPageResolver, $pageName);
}
return $default;
}
/**
* Set the current page resolver callback.
*
* @param ¥Closure $resolver
* @return void
*/
public static function currentPageResolver(Closure $resolver)
{
static::$currentPageResolver = $resolver;
}
26
¥Illuminate¥Pagination¥AbstractPaginator
public static function resolveCurrentPage($pageName = 'page', $default = 1)
{
if (isset(static::$currentPageResolver)) {
return call_user_func(static::$currentPageResolver, $pageName);
}
return $default;
}
/**
* Set the current page resolver callback.
*
* @param ¥Closure $resolver
* @return void
*/
public static function currentPageResolver(Closure $resolver)
{
static::$currentPageResolver = $resolver;
}
$currentPageResolver を呼び出している
$currentPageResolver は……?
27
¥Illuminate¥Pagination¥AbstractPaginator
public static function resolveCurrentPage($pageName = 'page', $default = 1)
{
if (isset(static::$currentPageResolver)) {
return call_user_func(static::$currentPageResolver, $pageName);
}
return $default;
}
/**
* Set the current page resolver callback.
*
* @param ¥Closure $resolver
* @return void
*/
public static function currentPageResolver(Closure $resolver)
{
static::$currentPageResolver = $resolver;
}
ここでセットされてる!
順当にクラス定義をさかのぼって行くと、ここで行き止まる
= の呼び出し箇所が見つからない
→ Laravel には ServiceProvider という仕組みがある
• アプリケーションの各所初期処理が行われる場所
28
行き止まり?
Paginator::currentPageResolver()
29
¥Illuminate¥Pagination¥PaginationServiceProvider
public function register()
{
Paginator::viewFactoryResolver(function () {
return $this->app['view'];
});
Paginator::currentPathResolver(function () {
return $this->app['request']->url();
});
Paginator::currentPageResolver(function ($pageName = 'page') {
$page = $this->app['request']->input($pageName);
if (filter_var($page, FILTER_VALIDATE_INT) !== false && (int) $page >= 1) {
return (int) $page;
}
return 1;
});
}
30
¥Illuminate¥Pagination¥PaginationServiceProvider
public function register()
{
Paginator::viewFactoryResolver(function () {
return $this->app['view'];
});
Paginator::currentPathResolver(function () {
return $this->app['request']->url();
});
Paginator::currentPageResolver(function ($pageName = 'page') {
$page = $this->app['request']->input($pageName);
if (filter_var($page, FILTER_VALIDATE_INT) !== false && (int) $page >= 1) {
return (int) $page;
}
return 1;
});
}
リクエストパラメータ ${pageName} を取得
31
¥Illuminate¥Pagination¥LengthAwarePaginator
// Controller にて
$users = App¥User::paginate(15);
DBから取得できる
(わかる)
引数でもらう
(わかる)
算出できる
(わかる)
??(わからない)
32
¥Illuminate¥Pagination¥LengthAwarePaginator
// Controller にて
$users = App¥User::paginate(15);
DBから取得できる
(わかる)
引数でもらう
(わかる)
算出できる
(わかる)
わかった!
Laravel の paginate は一体何をやっているのか
• Laravel の paginate は一見アクロバティックだが
意外と副作用が無い形になっていた
• Laravel のコードを追って行って
abstract class や interface で行き止まったら
それっぽい ServiceProvider を探すと良い
• こういうの調査するのに PhpStorm が便利!(Go To Declaration)
• 要 larvae-ide-helper
https://github.com/barryvdh/laravel-ide-helper
34
まとめ

More Related Content

PDF
コンテナの作り方「Dockerは裏方で何をしているのか?」
PDF
サーバーサイドでの非同期処理で色々やったよ
PDF
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
PDF
ソーシャルゲームのためのデータベース設計
PDF
ソーシャルゲーム案件におけるDB分割のPHP実装
PDF
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
PDF
Dockerfile を書くためのベストプラクティス解説編
PDF
例外設計における大罪
コンテナの作り方「Dockerは裏方で何をしているのか?」
サーバーサイドでの非同期処理で色々やったよ
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
ソーシャルゲームのためのデータベース設計
ソーシャルゲーム案件におけるDB分割のPHP実装
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
Dockerfile を書くためのベストプラクティス解説編
例外設計における大罪

What's hot (20)

PDF
テスト文字列に「うんこ」と入れるな
PDF
Dockerからcontainerdへの移行
PDF
ストリーム処理を支えるキューイングシステムの選び方
PPTX
SPAセキュリティ入門~PHP Conference Japan 2021
PDF
Docker Compose 徹底解説
PDF
Yahoo!ニュースにおけるBFFパフォーマンスチューニング事例
PPTX
さくっと理解するSpring bootの仕組み
PPTX
Istioサービスメッシュ入門
PDF
大規模ソーシャルゲームを支える技術~PHP+MySQLを使った高負荷対策~
PPTX
Kubernetesでの性能解析 ~なんとなく遅いからの脱却~(Kubernetes Meetup Tokyo #33 発表資料)
PDF
Where狙いのキー、order by狙いのキー
PDF
Dockerイメージ管理の内部構造
PPTX
Redisの特徴と活用方法について
PDF
モダン PHP テクニック 12 選 ―PsalmとPHP 8.1で今はこんなこともできる!―
PDF
分散トレーシング技術について(Open tracingやjaeger)
PDF
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
PDF
強いて言えば「集約どう実装するのかな、を考える」な話
PDF
O/Rマッパーによるトラブルを未然に防ぐ
PDF
怖くないSpring Bootのオートコンフィグレーション
テスト文字列に「うんこ」と入れるな
Dockerからcontainerdへの移行
ストリーム処理を支えるキューイングシステムの選び方
SPAセキュリティ入門~PHP Conference Japan 2021
Docker Compose 徹底解説
Yahoo!ニュースにおけるBFFパフォーマンスチューニング事例
さくっと理解するSpring bootの仕組み
Istioサービスメッシュ入門
大規模ソーシャルゲームを支える技術~PHP+MySQLを使った高負荷対策~
Kubernetesでの性能解析 ~なんとなく遅いからの脱却~(Kubernetes Meetup Tokyo #33 発表資料)
Where狙いのキー、order by狙いのキー
Dockerイメージ管理の内部構造
Redisの特徴と活用方法について
モダン PHP テクニック 12 選 ―PsalmとPHP 8.1で今はこんなこともできる!―
分散トレーシング技術について(Open tracingやjaeger)
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
強いて言えば「集約どう実装するのかな、を考える」な話
O/Rマッパーによるトラブルを未然に防ぐ
怖くないSpring Bootのオートコンフィグレーション
Ad

More from Shohei Okada (20)

PDF
「登壇しているひとは偉い」という話
PDF
PHP-FPM の子プロセス制御方法と設定をおさらいしよう
PDF
PHP 8.0 の新記法を試してみよう!
PDF
自分たちのコードを Composer パッケージに分割して開発する
PDF
クリーンアーキテクチャの考え方にもとづく Laravel との付き合い方 #shuuumai
PDF
クリーンアーキテクチャの考え方にもとづく Laravel との付き合い方 #phpconokinawa
PDF
クリーンアーキテクチャの考え方にもとづく Laravel との付き合い方 #phpcondo
PDF
Laravel でやってみるクリーンアーキテクチャ #phpconfuk
PDF
エラー時にログに出力する情報と画面に表示する情報を分ける #LaravelTokyo
PDF
スペシャリストとして組織をつくる、というキャリア
PDF
PHP でも活用できる Makefile
PDF
はじめての Go 言語のプロジェクトを AWS Lambda + API Gateway でやったのでパッケージ構成を晒すよ
PDF
Laravel × レイヤードアーキテクチャを実践して得られた知見と反省 / Practice of Laravel with layered archi...
PDF
働き方が大きく変わった 入社3年目のときのとあるエピソード
PDF
Laravel で API バージョニングを実装するなら
PDF
Laravel における Blade 拡張のツラミ
PDF
2017 年度を振り返って ~アウトプット編~
PDF
Laravel × レイヤードアーキテクチャをやってみている話
PDF
Laravel 5.6 デフォルトの例外ハンドリング処理をまとめてみた
PDF
チームで「きちんと」Laravel を使っていくための取り組み
「登壇しているひとは偉い」という話
PHP-FPM の子プロセス制御方法と設定をおさらいしよう
PHP 8.0 の新記法を試してみよう!
自分たちのコードを Composer パッケージに分割して開発する
クリーンアーキテクチャの考え方にもとづく Laravel との付き合い方 #shuuumai
クリーンアーキテクチャの考え方にもとづく Laravel との付き合い方 #phpconokinawa
クリーンアーキテクチャの考え方にもとづく Laravel との付き合い方 #phpcondo
Laravel でやってみるクリーンアーキテクチャ #phpconfuk
エラー時にログに出力する情報と画面に表示する情報を分ける #LaravelTokyo
スペシャリストとして組織をつくる、というキャリア
PHP でも活用できる Makefile
はじめての Go 言語のプロジェクトを AWS Lambda + API Gateway でやったのでパッケージ構成を晒すよ
Laravel × レイヤードアーキテクチャを実践して得られた知見と反省 / Practice of Laravel with layered archi...
働き方が大きく変わった 入社3年目のときのとあるエピソード
Laravel で API バージョニングを実装するなら
Laravel における Blade 拡張のツラミ
2017 年度を振り返って ~アウトプット編~
Laravel × レイヤードアーキテクチャをやってみている話
Laravel 5.6 デフォルトの例外ハンドリング処理をまとめてみた
チームで「きちんと」Laravel を使っていくための取り組み
Ad

Laravel の paginate は一体何をやっているのか