はじめに
LaravelのミドルウェアはコントローラーにPOSTなどで送られてきたデータに対して、送る前に予め何らかの処理をさせることができる。
今回は、その性質を利用して、キーワード検索用に配列にする処理を作成する。
要件
キーワード検索フォームは、キーワード1 キーワード2
というようにスペースで区切って検索対象にするワードを入力する使い方が多い。このため、単純にスペースで分割すればいいと考えがちだが、使う人は全角スペースも使うことを考慮しなければならない。
また、複数回スペースを入力されたり、同じキーワードが複数回入力されたときにそのままSQLパラメータとして使うのは非効率的である。
この手の処理は検索系ではどこでも使うので、通常は、共通のライブラリなどを参照するようにすることを考えるが、Laravelのミドルウェア機能を使って、透過的に使用することで、コントローラーのコードをすっきりさせることが可能である。
実際作ってみた
<?php
/**
* キーワードを配列化
*
* @author Logue <logue@hotmail.co.jp>
* @copyright 2019 Logue
* @license MIT
*/
namespace App\Http\Middleware;
use Closure;
class KeywordExploder
{
/**
* キーワードを空白文字で分割し配列にする。
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
*
* @return mixed
*/
public function handle($request, Closure $next)
{
$keyword = $request->input('keyword');
$ret = [];
if (!empty($keyword)){
// +を半角スペースに変換(GETメソッド対策)
$keyword = str_replace('+', ' ', $keyword);
// 全角スペースを半角スペースに変換
$keyword = str_replace(' ', ' ', $keyword);
// %はSQL実行時にLIKEのパラメータとして使うのでスペースにする。
$keyword = str_replace('%', ' ', $keyword);
// 取得したキーワードのスペースの重複を除く。
$keyword = preg_replace('/\s(?=\s)/', '', $keyword);
// キーワード文字列の前後のスペースを削除する
$keyword = trim($keyword);
if (!empty($keyword) || $keyword !== '') {
// 半角カナを全角カナへ変換
$keyword = mb_convert_kana($keyword, 'KV');
// 半角スペースで配列にし、重複は削除する
$ret['keyword'] = array_unique(explode(' ', $keyword));
}
}
$request->merge($ret);
return $next($request);
}
}
直訳するとキーワード発破者になってしまうが、これはexplode
命令で配列にしているからであって深い意味はない。
使い方
ダウンロードしたKeywordExploder.php
をapp/Http/Middleware
内に置き、Kernel.php
の$routeMiddleware
に以下の行を追加。
'keyword' => \App\Http\Middleware\KeywordExploder::class,
次に、routes/web.php
の検索処理のルーティング部分に->middleware('keyword')
と入れる。
あとは、コントローラーやモデル側のキーワード検索のSQLを発行する処理の部分で
$keywords = $request->input('keyword');
if(!empty($keywords)) {
foreach ($keywords as $keyword) {
$query->where('name','like','%'.$keyword.'%')
}
}
みたいにforeach
で回して使用する。