前提
- Laravel 8.x
やりたいこと
- Collectionの操作で、
「Collection内にある要素の内、nullの値を消したい!
状況
- 例えば、orderとuserは1対多の関係であり、
users()
というメソッドでorderに紐づくuserを取得できる場合、
$users = Order::find($order_id)->users()->get();
dd($users);
- デバック結果↓
Illuminate\Database\Eloquent\Collection {#** ▼
#items: array:6 [▼
0 => App\Models\User {#** ▶}
1 => App\Models\User {#** ▶}
2 => null // 消したい
3 => App\Models\User {#** ▶}
4 => null // 消したい
5 => App\Models\User {#** ▶}
]
}
- こんな感じで要素にnullを含むCollectionとなったとき、値がnullの要素を消したい、という状況
対策案
- 今回の「やりたいこと」をかなえる手段で一番に浮かんだのは、
whereNotNull
というCollectionメソッド- メソッド名からしていかにも感。
- ただ、公式を見ると、引数が必要そうな感じ。。。
- 「使えないかな…」と思ってダメもとで引数無しで以下のように使ってみたところ、、、
$users = Order::find($order_id)->users()
->get()
->whereNotNull(); // 引数無しで使ってみる
dd($users);
- デバック結果↓
Illuminate\Database\Eloquent\Collection {#** ▼
#items: array:4 [▼
0 => App\Models\User {#** ▶}
1 => App\Models\User {#** ▶}
2 => App\Models\User {#** ▶}
3 => App\Models\User {#** ▶}
]
}
- イケんじゃん笑
ということで一件落着。
- とはいえ、「どういうことだ?」ということでvender配下の
whereNotNull
メソッドの定義場所を漁ると以下のようになってました
public function whereNotNull($key = null)
{
return $this->where($key, '!==', null);
}
- 予想通りではあったけど、引数$keyの初期値がnullとしているので、引数なしでも使えるんですねー
余談
同じnull系を扱うwhereNull
も同じく$key=nullなので引数無しで使えますね
public function whereNull($key = null)
{
return $this->whereStrict($key, null);
}
所見
- こうやってvender配下を見るようになると、意外な使い方できるんだ!って気づきがあってオモロイですね
- これは個人的な思いですが、
where
メソッドって引数にクロージャ使えるようにしたい、って思うときないですかね?- 例えば、「とあるコレクション内にあるモデルのリレーション先のプロパティの値と他の値を比較して一致したときに、その値を返す」みたいな処理
whereの使用例(クロージャ―を引数で使えるなら、、、の前提)
-
先ほどの
$users
が以下を持っているとしてIlluminate\Database\Eloquent\Collection {#** ▼ #items: array:4 [▼ 0 => App\Models\User {#** ▶} 1 => App\Models\User {#** ▶} 2 => App\Models\User {#** ▶} 3 => App\Models\User {#** ▶} ] }
-
もし、whereでクロージャが使える前提で書くならこんな感じ
for($i=0; $i < 10; $i++){
$users->where(function($user)use($i){
return $user->id === $i;
});
}
dd($users);
これでデバッグの結果が$user→id
と$i
が一致するモデルを返す、見たいに使えたらいいのにな、と思った次第です。
「いやいや、既存のCollectionメソッドで行けるでしょ!」
などツッコミ大歓迎です。どうぞご鞭撻のほどお願いします。
最後までお読みいただきありがとうございました!