親子リレーションで、親子どっちの条件でも検索できて、子の検索(or親の検索)に引っかかった親子の組み合わせcollectionだけ取得したい!
Post(親)
Comment(子)
で、例えば「さしすせそ」という単語が含まれている組み合わせだけ取得したい!(親でも子でもいい)
Post1(あいうえお)
├Comment1(かきくけこ)
├Comment2(さしすせそ)
└Comment3(たちつてと)
Post1->Comment2の組み合わせだけのCollectionを返して欲しい!
前回のやり方だと、親に「さしすせそ」が含まれていないと、まず親が検索にヒットしないので、その子の検索条件まで行かない…。
laravel8のhasmany(リレーション)のwhere句を、検索条件に従って動的に変更したい!(親whereと子whereのAND検索がしたい!)
じゃあ、どうやんの?と考えてみたら、eloquentのjoin()を使えば、子レコードの条件で親レコードもひっぱってこれる。
ただし、このままだと親レコードに紐づく子レコードが全部取得されてしまうので、同条件でhasmanyで絞り込む!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
// requestの検索条件に従い、動的に子テーブルとのリレーション条件を定義する Post::addDynamicRelation('comments', function(Post $Post) use ($request){ // 基本のリレーション定義を記述 $hasmany = $Post->hasMany(Comment::class); // 検索条件を追加していく if(!empty($request['body'])){ $hasmany->where('body', 'like', "%$request['title']%"); } return $hasmany; }); // eloquentとクエリビルダの合せ技! $query = Post::query() ->select('posts.*') ->distinct() // joinで同じレコードが重複するので // 同じ条件を、joinとaddDynamicRelationの両方に書く! // joinでComment条件からPostレコードを取得して、addDynamicRelationでCommentレコードを絞り込む! ->join('comments', function ($join) use ($request){ $join->on('posts.id', '=', 'comments.post_id'); // soft_detetesはjoinだと自動的に動作しないので明示的に記述する $join->whereNull('comments.deleted_at'); // コメントの条件だけで、投稿レコードも取得する! $join->where('comments.body','like', '%さしすせそ%'); }); // joinしても、普通のeloquentと同じくwhereで検索できる。$query = Post::query()の続き $query->where('body','like', '%さしすせそ%'); // joinとは別に、addDynamicRelationで動的にhasmanyで同じ条件で絞り込む // https://www.messiahworks.com/archives/24532 $posts = $query->with('comments')->get(); |
望んた実装にはなったけど、joinとhasmanyで同じ条件を2回記述するのは何だかな~。
なんとか一箇所で記述する方法は無いものだろうか?