🐘
[Laravel][Collection] 文字列の部分一致を抽出する小技
published_at: 2019-10-11 22:51
Laravel の Collection 、超便利なようで、ちょいちょいできないことがあるような感じがするのですが、
やりようによってはできたりもするという割と良い事例だなと思ったので整理して投稿します。
やりたかったこと
Collection中のとある key カラムの文字列値が、指定の val 文字列と部分一致している行の抽出。
SQLで言うと、WHERE key LIKE "%{target}%"
のような感じ。
見つけた小技
$filtered = $records->filter(function ($record) use ($key, $val) {
return strpos($record[$key], $val) !== false;
});
説明
変数名 | 説明 | 備考 |
---|---|---|
$records |
抽出元のデータ群 | |
filter | Collectionクラスのメソッド |
Laravel docs, Laravel API reference |
$record |
↑の単数形。「個々のレコード」という意味に相当 | |
$key |
カラム名を入れる変数 | |
$val |
これと一致しているところがあったら 抽出したい文字列を入れる変数 |
|
strpos | PHPの関数 | PHP manual(ja) |
$record[$key] |
格納されている値 | |
$filtered |
部分一致するレコードを抽出した結果 |
-
strpos
を使っているのがちょっとしたポイント。
ここの関数(と判定)を変えることで、目的に応じて違った抽出もやれそう。
試した環境
- PHP 7.3.10
- Laravel 5.8.35
検証内容
tinker を利用
ここをクリックすると展開されます
# php artisan tinker
Psy Shell v0.9.9 (PHP 7.3.10 cli) by Justin Hileman
>>> $records = collect([
... ['id' => 1, 'phrase' => 'あいうえ'],
... ['id' => 2, 'phrase' => 'いうえお'],
... ['id' => 3, 'phrase' => 'うえおあ'], //おあ includes
... ['id' => 4, 'phrase' => 'えおあい'], //おあ includes
... ['id' => 5, 'phrase' => 'おあいう'], //おあ includes
... ]);
=> Illuminate\Support\Collection {#3278
all: [
[
"id" => 1,
"phrase" => "あいうえ",
],
[
"id" => 2,
"phrase" => "いうえお",
],
[
"id" => 3,
"phrase" => "うえおあ",
],
[
"id" => 4,
"phrase" => "えおあい",
],
[
"id" => 5,
"phrase" => "おあいう",
],
],
}
>>> $conditions = ['phrase' => 'おあ']; //LIKE的な検索をしたい文字列
>>> foreach ($conditions as $key => $val) {
... if (in_array($key, [
... 'phrase',
... ])) {
... $filtered = $records->filter(function ($record) use ($key, $val) {
... return \strpos($record[$key], $val) !== false;
... });
... $records = $filtered;
... }
... }
>>> $filtered->all();
=> [
2 => [
"id" => 3,
"phrase" => "うえおあ",
],
3 => [
"id" => 4,
"phrase" => "えおあい",
],
4 => [
"id" => 5,
"phrase" => "おあいう",
],
]
>>>
Discussion