WHEREでクエリ結果を絞り込んで、その結果をページネーションするところで、指定ページが効かないなど少しハマったのでメモ。(現在October CMSで使用しているLaravelは5.5なので、それ以降のLaravelバージョンでは挙動がもしかしたら違うかもしれない。)
ググると「MyModel::paginate(10, ['*'])
でOK」みたいな情報はたくさん出てくるが、WHERE
などで絞り込むときはどうするのか。
また、常にWHERE
があるとは限らないので、MyModel::where()
を使うのもキレイではない。
そして、取得するカラムも指定したい。
うまくいった書き方
-
MyModel::select($columns)
でクエリオブジェクトを作成する。 - クエリオブジェクトに対して
where
メソッドでクエリ条件を必要に応じて追加する。 - クエリオブジェクトで
paginate
メソッドでページネータを作成する。
下記はWeb APIのコントローラ内でクエリ処理を実施している例。
public function list()
{
$columns = [
'id',
'name',
'description',
'type',
];
// Search conditions
$name = Input::get('name');
$type = Input::get('type');
$page = Input::get('page');
$perPage = Input::get('per_page', 15); // 15 is framework default
// To specify columns, they must be specified in select().
$query = MyModel::select($columns); // <- (1)
if (!empty($name)) {
$query = $query->where('name', 'like', '%'.$name.'%'); // <- (2)
}
if (!empty($type)) {
$query = $query->where('type', '=', $type); // <- (2)
}
// For proper functionality of pagination, columns also passed to paginate()
return $query->paginate($perPage, $columns, 'page', $page); // <- (3)
}
ポイント:カラムの指定について
(1)のMyModel::select($columns)
でカラムを指定しないと全てのデータが返される
(1)で指定していても(3)の$query->paginate()
でも指定する必要がある。ここで指定しないとページ指定が効かないなどページネーションが正常に動作しない。
次ページ、前ページのURLの修正
ページネータは次ページや前ページのURLを提供してくれるが、GETパラメータで渡した検索条件を同様にこれらのURLには入れてくれないので自分で入れる必要がある。
上記の例でreturn
で返しているページネータオブジェクトのappends
メソッドでこれらのURLにGETパラメータを追加することができる。受け取ったのと同じパラメータをそのまま入れてやれば良い。
// For proper functionality of pagination, columns also passed to paginate()
$paginator = $query->paginate($perPage, $columns, 'page', $page);
// Add query string to the next/prev URLs.
$queryParams = [
'name' => $name,
'type' => $type,
'per_page' => $perPage,
];
if (!empty($queryParams)) {
$paginator->appends($queryParams);
}
return $paginator;