Skip to content

Commit 59e16b9

Browse files
authored
PHPORM-232 Support whereLike and whereNotLike (#3108)
* PHPORM-232 Support whereLike and whereNotLike * Check required methods from Laravel in tests
1 parent a2eb54a commit 59e16b9

File tree

3 files changed

+180
-112
lines changed

3 files changed

+180
-112
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ All notable changes to this project will be documented in this file.
44
## [4.8.0] - next
55

66
* Add `Query\Builder::incrementEach()` and `decrementEach()` methods by @SmallRuralDog in [#2550](https://github.com/mongodb/laravel-mongodb/pull/2550)
7+
* Add `Query\Builder::whereLike()` and `whereNotLike()` methods by @GromNaN in [#3108](https://github.com/mongodb/laravel-mongodb/pull/3108)
78
* Deprecate `Connection::collection()` and `Schema\Builder::collection()` methods by @GromNaN in [#3062](https://github.com/mongodb/laravel-mongodb/pull/3062)
89
* Deprecate `Model::$collection` property to customize collection name. Use `$table` instead by @GromNaN in [#3064](https://github.com/mongodb/laravel-mongodb/pull/3064)
910

src/Query/Builder.php

+9-1
Original file line numberDiff line numberDiff line change
@@ -1266,7 +1266,8 @@ protected function compileWhereBasic(array $where): array
12661266
// All backslashes are converted to \\, which are needed in matching regexes.
12671267
preg_quote($value),
12681268
);
1269-
$value = new Regex('^' . $regex . '$', 'i');
1269+
$flags = $where['caseSensitive'] ?? false ? '' : 'i';
1270+
$value = new Regex('^' . $regex . '$', $flags);
12701271

12711272
// For inverse like operations, we can just use the $not operator with the Regex
12721273
$operator = $operator === 'like' ? '=' : 'not';
@@ -1324,6 +1325,13 @@ protected function compileWhereNotIn(array $where): array
13241325
return [$where['column'] => ['$nin' => array_values($where['values'])]];
13251326
}
13261327

1328+
protected function compileWhereLike(array $where): array
1329+
{
1330+
$where['operator'] = $where['not'] ? 'not like' : 'like';
1331+
1332+
return $this->compileWhereBasic($where);
1333+
}
1334+
13271335
protected function compileWhereNull(array $where): array
13281336
{
13291337
$where['operator'] = '=';

tests/Query/BuilderTest.php

+170-111
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,18 @@
2626
use function collect;
2727
use function method_exists;
2828
use function now;
29+
use function sprintf;
2930
use function var_export;
3031

3132
class BuilderTest extends TestCase
3233
{
3334
#[DataProvider('provideQueryBuilderToMql')]
34-
public function testMql(array $expected, Closure $build): void
35+
public function testMql(array $expected, Closure $build, ?string $requiredMethod = null): void
3536
{
37+
if ($requiredMethod && ! method_exists(Builder::class, $requiredMethod)) {
38+
$this->markTestSkipped(sprintf('Method "%s::%s()" does not exist.', Builder::class, $requiredMethod));
39+
}
40+
3641
$builder = $build(self::getBuilder());
3742
$this->assertInstanceOf(Builder::class, $builder);
3843
$mql = $builder->toMql();
@@ -748,6 +753,48 @@ function (Builder $builder) {
748753
fn (Builder $builder) => $builder->where('name', 'like', '_ac__me_'),
749754
];
750755

756+
yield 'whereLike' => [
757+
['find' => [['name' => new Regex('^1$', 'i')], []]],
758+
fn
759+
(Builder $builder) => $builder->whereLike('name', '1'),
760+
'whereLike',
761+
];
762+
763+
yield 'whereLike case not sensitive' => [
764+
['find' => [['name' => new Regex('^1$', 'i')], []]],
765+
fn
766+
(Builder $builder) => $builder->whereLike('name', '1', false),
767+
'whereLike',
768+
];
769+
770+
yield 'whereLike case sensitive' => [
771+
['find' => [['name' => new Regex('^1$', '')], []]],
772+
fn
773+
(Builder $builder) => $builder->whereLike('name', '1', true),
774+
'whereLike',
775+
];
776+
777+
yield 'whereNotLike' => [
778+
['find' => [['name' => ['$not' => new Regex('^1$', 'i')]], []]],
779+
fn
780+
(Builder $builder) => $builder->whereNotLike('name', '1'),
781+
'whereNotLike',
782+
];
783+
784+
yield 'whereNotLike case not sensitive' => [
785+
['find' => [['name' => ['$not' => new Regex('^1$', 'i')]], []]],
786+
fn
787+
(Builder $builder) => $builder->whereNotLike('name', '1', false),
788+
'whereNotLike',
789+
];
790+
791+
yield 'whereNotLike case sensitive' => [
792+
['find' => [['name' => ['$not' => new Regex('^1$', '')]], []]],
793+
fn
794+
(Builder $builder) => $builder->whereNotLike('name', '1', true),
795+
'whereNotLike',
796+
];
797+
751798
$regex = new Regex('^acme$', 'si');
752799
yield 'where BSON\Regex' => [
753800
['find' => [['name' => $regex], []]],
@@ -1161,142 +1208,154 @@ function (Builder $elemMatchQuery): void {
11611208
];
11621209

11631210
// Method added in Laravel v10.47.0
1164-
if (method_exists(Builder::class, 'whereAll')) {
1165-
/** @see DatabaseQueryBuilderTest::testWhereAll */
1166-
yield 'whereAll' => [
1167-
[
1168-
'find' => [
1169-
['$and' => [['last_name' => 'Doe'], ['email' => 'Doe']]],
1170-
[], // options
1171-
],
1211+
/** @see DatabaseQueryBuilderTest::testWhereAll */
1212+
yield 'whereAll' => [
1213+
[
1214+
'find' => [
1215+
['$and' => [['last_name' => 'Doe'], ['email' => 'Doe']]],
1216+
[], // options
11721217
],
1173-
fn(Builder $builder) => $builder->whereAll(['last_name', 'email'], 'Doe'),
1174-
];
1175-
1176-
yield 'whereAll operator' => [
1177-
[
1178-
'find' => [
1179-
[
1180-
'$and' => [
1181-
['last_name' => ['$not' => new Regex('^.*Doe.*$', 'i')]],
1182-
['email' => ['$not' => new Regex('^.*Doe.*$', 'i')]],
1183-
],
1218+
],
1219+
fn
1220+
(Builder $builder) => $builder->whereAll(['last_name', 'email'], 'Doe'),
1221+
'whereAll',
1222+
];
1223+
1224+
yield 'whereAll operator' => [
1225+
[
1226+
'find' => [
1227+
[
1228+
'$and' => [
1229+
['last_name' => ['$not' => new Regex('^.*Doe.*$', 'i')]],
1230+
['email' => ['$not' => new Regex('^.*Doe.*$', 'i')]],
11841231
],
1185-
[], // options
11861232
],
1233+
[], // options
11871234
],
1188-
fn(Builder $builder) => $builder->whereAll(['last_name', 'email'], 'not like', '%Doe%'),
1189-
];
1190-
1191-
/** @see DatabaseQueryBuilderTest::testOrWhereAll */
1192-
yield 'orWhereAll' => [
1193-
[
1194-
'find' => [
1195-
[
1196-
'$or' => [
1197-
['first_name' => 'John'],
1198-
['$and' => [['last_name' => 'Doe'], ['email' => 'Doe']]],
1199-
],
1235+
],
1236+
fn
1237+
(Builder $builder) => $builder->whereAll(['last_name', 'email'], 'not like', '%Doe%'),
1238+
'whereAll',
1239+
];
1240+
1241+
/** @see DatabaseQueryBuilderTest::testOrWhereAll */
1242+
yield 'orWhereAll' => [
1243+
[
1244+
'find' => [
1245+
[
1246+
'$or' => [
1247+
['first_name' => 'John'],
1248+
['$and' => [['last_name' => 'Doe'], ['email' => 'Doe']]],
12001249
],
1201-
[], // options
12021250
],
1251+
[], // options
12031252
],
1204-
fn(Builder $builder) => $builder
1205-
->where('first_name', 'John')
1206-
->orWhereAll(['last_name', 'email'], 'Doe'),
1207-
];
1208-
1209-
yield 'orWhereAll operator' => [
1210-
[
1211-
'find' => [
1212-
[
1213-
'$or' => [
1214-
['first_name' => new Regex('^.*John.*$', 'i')],
1215-
[
1216-
'$and' => [
1217-
['last_name' => ['$not' => new Regex('^.*Doe.*$', 'i')]],
1218-
['email' => ['$not' => new Regex('^.*Doe.*$', 'i')]],
1219-
],
1253+
],
1254+
fn
1255+
(Builder $builder) => $builder
1256+
->where('first_name', 'John')
1257+
->orWhereAll(['last_name', 'email'], 'Doe'),
1258+
'orWhereAll',
1259+
];
1260+
1261+
yield 'orWhereAll operator' => [
1262+
[
1263+
'find' => [
1264+
[
1265+
'$or' => [
1266+
['first_name' => new Regex('^.*John.*$', 'i')],
1267+
[
1268+
'$and' => [
1269+
['last_name' => ['$not' => new Regex('^.*Doe.*$', 'i')]],
1270+
['email' => ['$not' => new Regex('^.*Doe.*$', 'i')]],
12201271
],
12211272
],
12221273
],
1223-
[], // options
12241274
],
1275+
[], // options
12251276
],
1226-
fn(Builder $builder) => $builder
1227-
->where('first_name', 'like', '%John%')
1228-
->orWhereAll(['last_name', 'email'], 'not like', '%Doe%'),
1229-
];
1230-
}
1277+
],
1278+
fn
1279+
(Builder $builder) => $builder
1280+
->where('first_name', 'like', '%John%')
1281+
->orWhereAll(['last_name', 'email'], 'not like', '%Doe%'),
1282+
'orWhereAll',
1283+
];
12311284

12321285
// Method added in Laravel v10.47.0
1233-
if (method_exists(Builder::class, 'whereAny')) {
1234-
/** @see DatabaseQueryBuilderTest::testWhereAny */
1235-
yield 'whereAny' => [
1236-
[
1237-
'find' => [
1238-
['$or' => [['last_name' => 'Doe'], ['email' => 'Doe']]],
1239-
[], // options
1240-
],
1286+
/** @see DatabaseQueryBuilderTest::testWhereAny */
1287+
yield 'whereAny' => [
1288+
[
1289+
'find' => [
1290+
['$or' => [['last_name' => 'Doe'], ['email' => 'Doe']]],
1291+
[], // options
12411292
],
1242-
fn(Builder $builder) => $builder->whereAny(['last_name', 'email'], 'Doe'),
1243-
];
1244-
1245-
yield 'whereAny operator' => [
1246-
[
1247-
'find' => [
1248-
[
1249-
'$or' => [
1250-
['last_name' => ['$not' => new Regex('^.*Doe.*$', 'i')]],
1251-
['email' => ['$not' => new Regex('^.*Doe.*$', 'i')]],
1252-
],
1293+
],
1294+
fn
1295+
(Builder $builder) => $builder->whereAny(['last_name', 'email'], 'Doe'),
1296+
'whereAny',
1297+
];
1298+
1299+
yield 'whereAny operator' => [
1300+
[
1301+
'find' => [
1302+
[
1303+
'$or' => [
1304+
['last_name' => ['$not' => new Regex('^.*Doe.*$', 'i')]],
1305+
['email' => ['$not' => new Regex('^.*Doe.*$', 'i')]],
12531306
],
1254-
[], // options
12551307
],
1308+
[], // options
12561309
],
1257-
fn(Builder $builder) => $builder->whereAny(['last_name', 'email'], 'not like', '%Doe%'),
1258-
];
1259-
1260-
/** @see DatabaseQueryBuilderTest::testOrWhereAny */
1261-
yield 'orWhereAny' => [
1262-
[
1263-
'find' => [
1264-
[
1265-
'$or' => [
1266-
['first_name' => 'John'],
1267-
['$or' => [['last_name' => 'Doe'], ['email' => 'Doe']]],
1268-
],
1310+
],
1311+
fn
1312+
(Builder $builder) => $builder->whereAny(['last_name', 'email'], 'not like', '%Doe%'),
1313+
'whereAny',
1314+
];
1315+
1316+
/** @see DatabaseQueryBuilderTest::testOrWhereAny */
1317+
yield 'orWhereAny' => [
1318+
[
1319+
'find' => [
1320+
[
1321+
'$or' => [
1322+
['first_name' => 'John'],
1323+
['$or' => [['last_name' => 'Doe'], ['email' => 'Doe']]],
12691324
],
1270-
[], // options
12711325
],
1326+
[], // options
12721327
],
1273-
fn(Builder $builder) => $builder
1274-
->where('first_name', 'John')
1275-
->orWhereAny(['last_name', 'email'], 'Doe'),
1276-
];
1277-
1278-
yield 'orWhereAny operator' => [
1279-
[
1280-
'find' => [
1281-
[
1282-
'$or' => [
1283-
['first_name' => new Regex('^.*John.*$', 'i')],
1284-
[
1285-
'$or' => [
1286-
['last_name' => ['$not' => new Regex('^.*Doe.*$', 'i')]],
1287-
['email' => ['$not' => new Regex('^.*Doe.*$', 'i')]],
1288-
],
1328+
],
1329+
fn
1330+
(Builder $builder) => $builder
1331+
->where('first_name', 'John')
1332+
->orWhereAny(['last_name', 'email'], 'Doe'),
1333+
'whereAny',
1334+
];
1335+
1336+
yield 'orWhereAny operator' => [
1337+
[
1338+
'find' => [
1339+
[
1340+
'$or' => [
1341+
['first_name' => new Regex('^.*John.*$', 'i')],
1342+
[
1343+
'$or' => [
1344+
['last_name' => ['$not' => new Regex('^.*Doe.*$', 'i')]],
1345+
['email' => ['$not' => new Regex('^.*Doe.*$', 'i')]],
12891346
],
12901347
],
12911348
],
1292-
[], // options
12931349
],
1350+
[], // options
12941351
],
1295-
fn(Builder $builder) => $builder
1296-
->where('first_name', 'like', '%John%')
1297-
->orWhereAny(['last_name', 'email'], 'not like', '%Doe%'),
1298-
];
1299-
}
1352+
],
1353+
fn
1354+
(Builder $builder) => $builder
1355+
->where('first_name', 'like', '%John%')
1356+
->orWhereAny(['last_name', 'email'], 'not like', '%Doe%'),
1357+
'orWhereAny',
1358+
];
13001359
}
13011360

13021361
#[DataProvider('provideExceptions')]

0 commit comments

Comments
 (0)