はじめに

Laravel で (a OR b) AND (c OR d) のように複合的な AND/OR 検索する方法について整理した。

TL;DR

  • where(fucntion($query)) を使う
  • ↑ の中で $query->where$query->orWhere を使う

目次

  1. はじめに
  2. TL;DR
  3. 環境・条件
  4. 詳細
    1. 前置き: 通常の AND/OR 検索
      1. AND 検索
      2. OR 検索
    2. 本題: 複雑な AND/OR 検索
  5. まとめ
  6. 参考文献

環境・条件

1
2
3
4
5
6
7
8
9
$ php -v
PHP 7.2.22-1+ubuntu16.04.1+deb.sury.org+1 (cli) (built: Sep 2 2019 12:54:12) ( NTS )

$ cat /etc/os-release
PRETTY_NAME="Ubuntu 16.04.3 LTS"

$ composer info laravel/framework
name : laravel/framework
versions : * v5.7.28

詳細

php artisan tinkertoSql() を使って検証した。

前置き: 通常の AND/OR 検索

a AND ba OR b は、where()orWhere のチェーンで実現できる。

AND 検索

where()->where() でチェーン。

1
2
3
4
5
// AND: where()->where()
>>> User::where('name', 'LIKE', '%yama%') \
->where('age', '<', 20) \
->toSql()
=> "select * from `users` where `name` LIKE ? and `age` < ?"

OR 検索

where()->orWhere() でチェーン

1
2
3
4
5
// OR: where()->orWhere()
>>> User::where('name', 'LIKE', '%yama%') \
->orWhere('name', 'LIKE', '%kawa%') \
->toSql()
=> "select * from `users` where `name` LIKE ? or `name` LIKE ?"

本題: 複雑な AND/OR 検索

(a OR b) AND (c OR d) を、上記と同じノリで実行するとこうなる。

1
2
3
4
5
6
>>> User::where('name', 'LIKE', '%yama%') \
->orWhere('name', 'LIKE', '%kawa%') \
->where('age', '>', '20') \
->orWhere('age', '<', '10') \
->toSql()
=> "select * from `users` where `name` LIKE ? or `name` LIKE ? and `age` > ? or `age` < ?"

(a AND b) OR c(a OR b) AND (c OR d)where(function($query)) を使ってこうすると良い。

(a AND b) OR c

1
2
3
4
5
6
7
8
// (a AND b) OR c
>>> User::where('name', 'LIKE', '%yama%') \
->where('age', '<', 20) \
->where(function($query){ \
// ↓は where でも可 \
$query->orWhere('age', '>', 30); \
})->toSql()
=> "select * from `users` where `name` LIKE ? and `age` < ? and (`age` > ?)"

(a OR b) AND (c OR d)

1
2
3
4
5
6
7
8
9
10
11
// (a OR b) AND (c OR d)
User::where(function($query) { \
// ↓は where でも可 \
$query->orWhere('age', '>', 18) \
->orWhere('age', '<', 10); \
})->where(function($query) { \
// ↓は where でも可 \
$query->orWhere('name', 'LIKE', '%taro%') \
->orWhere('name', 'LIKE', '%hana%'); \
})->toSql()
=> "select * from `users` where (`age` > ? or `age` < ?) and (`name` LIKE ? or `name` LIKE ?)"

まとめ

  • where(fucntion($query)) を使う
  • ↑ の中で $query->where$query->orWhere を使う

参考文献

関連記事