From 8b405eb2a40f8458a816c02d1def56f5304403b7 Mon Sep 17 00:00:00 2001 From: Laravel Freelancer NL <36150929+LaravelFreelancerNL@users.noreply.github.com> Date: Sun, 10 Nov 2024 20:49:47 +0100 Subject: [PATCH] 167 support wherelike orwherelike wherenotlike orwherenotlike (#169) * feature: Added support for whereLike/orWhereLike/whereNotLike/orWhereNotLike * docs: added whereLike / orWhereLike / whereNotLike / orWhereNotLike --- docs/compatibility-list.md | 4 +- src/Query/Concerns/BuildsWheres.php | 21 +++++++ src/Query/Concerns/CompilesFilters.php | 30 ++++++++++ tests/Query/WheresTest.php | 78 +++++++++++++++++++++++++- 4 files changed, 130 insertions(+), 3 deletions(-) diff --git a/docs/compatibility-list.md b/docs/compatibility-list.md index 1ea57d7..aa39b30 100644 --- a/docs/compatibility-list.md +++ b/docs/compatibility-list.md @@ -74,7 +74,9 @@ rightJoin / rightJoinSub / joinWhere? where / orWhere / whereNot / orWhereNot / whereColumn / whereExists whereBetween / whereNotBetween / whereBetweenColumns / whereNotBetweenColumns / whereJsonContains / whereJsonLength / -whereIn / whereNotIn / whereNone / orWhereNone / whereNot / orWhereNot / +whereIn / whereNotIn / +whereLike / orWhereLike / whereNotLike / orWhereNotLike / +whereNone / orWhereNone / whereNot / orWhereNot / whereNull / whereNotNull / whereDate / whereMonth / whereDay / whereYear / whereTime / whereRaw (use AQL) / diff --git a/src/Query/Concerns/BuildsWheres.php b/src/Query/Concerns/BuildsWheres.php index e4dec60..55d302e 100644 --- a/src/Query/Concerns/BuildsWheres.php +++ b/src/Query/Concerns/BuildsWheres.php @@ -435,6 +435,27 @@ public function whereJsonLength($column, $operator, $value = null, $boolean = 'a return $this; } + /** + * Add a "where like" clause to the query. + * + * @param \Illuminate\Contracts\Database\Query\Expression|string $column + * @param string $value + * @param bool $caseSensitive + * @param string $boolean + * @param bool $not + * @return $this + */ + public function whereLike($column, $value, $caseSensitive = false, $boolean = 'and', $not = false) + { + $type = 'Like'; + + $value = $this->bindValue($value); + + $this->wheres[] = compact('type', 'column', 'value', 'caseSensitive', 'boolean', 'not'); + + return $this; + } + /** * Add a "where null" clause to the query. * diff --git a/src/Query/Concerns/CompilesFilters.php b/src/Query/Concerns/CompilesFilters.php index d38b770..291ed47 100644 --- a/src/Query/Concerns/CompilesFilters.php +++ b/src/Query/Concerns/CompilesFilters.php @@ -405,6 +405,36 @@ protected function filterYear(IlluminateQueryBuilder $query, $filter) return implode(' ', $predicate); } + /** + * Compile a filter month clause. + * + * @param IlluminateQueryBuilder $query + * @param array $filter + * @return string + * @throws \Exception + */ + protected function filterLike(IlluminateQueryBuilder $query, $filter) + { + $column = $this->normalizeColumn($query, $filter['column']); + $value = $this->parameter($filter['value']); + + $predicate = []; + + $filter = $this->normalizeOperator($filter); + + $predicate[0] = ($filter['caseSensitive']) ? $column : 'LOWER(' . $column . ')'; + $predicate[1] = 'LIKE'; + $predicate[2] = ($filter['caseSensitive']) ? $value : 'LOWER(' . $value . ')'; + + $result = implode(' ', $predicate); + + if ($filter['not']) { + $result = 'NOT (' . $result . ')'; + } + + return $result; + } + /** * Compile a filter month clause. * diff --git a/tests/Query/WheresTest.php b/tests/Query/WheresTest.php index f3e244e..d243b7b 100644 --- a/tests/Query/WheresTest.php +++ b/tests/Query/WheresTest.php @@ -644,8 +644,6 @@ ->orWhereNot('surname', 'Lannister') ->get(); - ray($results); - expect($results->count())->toBe(27); }); @@ -661,3 +659,79 @@ expect($results->count())->toBe(27); }); + +test('whereLike', function () { + $query = \DB::table('houses') + ->whereLike('en.coat-of-arms', '%dragon%'); + + $binds = $query->getBindings(); + $bindKeys = array_keys($binds); + + $this->assertSame( + 'FOR houseDoc IN houses FILTER LOWER(`houseDoc`.`en`.`coat-of-arms`) LIKE LOWER(@' . $bindKeys[0] + . ') RETURN houseDoc', + $query->toSql(), + ); + + $results = $query->get(); + expect($results->count())->toBe(1); + expect(($results->first())->name)->toBe('Targaryen'); +}); + +test('orWhereLike', function () { + $query = \DB::table('houses') + ->where('name', 'Stark') + ->orWhereLike('en.coat-of-arms', '%dragon%'); + + $binds = $query->getBindings(); + $bindKeys = array_keys($binds); + + $this->assertSame( + 'FOR houseDoc IN houses FILTER `houseDoc`.`name` == @' . $bindKeys[0] + . ' or LOWER(`houseDoc`.`en`.`coat-of-arms`) LIKE LOWER(@' . $bindKeys[1] + . ') RETURN houseDoc', + $query->toSql(), + ); + + $results = $query->get(); + expect($results->count())->toBe(2); + expect(($results->first())->name)->toBe('Stark'); +}); + +test('whereNotLike', function () { + $query = \DB::table('houses') + ->whereNotLike('en.coat-of-arms', '%dragon%'); + + $binds = $query->getBindings(); + $bindKeys = array_keys($binds); + + $this->assertSame( + 'FOR houseDoc IN houses FILTER NOT (LOWER(`houseDoc`.`en`.`coat-of-arms`) LIKE LOWER(@' . $bindKeys[0] + . ')) RETURN houseDoc', + $query->toSql(), + ); + + $results = $query->get(); + expect($results->count())->toBe(2); + expect(($results->first())->name)->toBe('Lannister'); +}); + +test('orWhereNotLike', function () { + $query = \DB::table('houses') + ->where('name', 'Stark') + ->orWhereNotLike('en.coat-of-arms', '%dragon%'); + + $binds = $query->getBindings(); + $bindKeys = array_keys($binds); + + $this->assertSame( + 'FOR houseDoc IN houses FILTER `houseDoc`.`name` == @' . $bindKeys[0] + . ' or NOT (LOWER(`houseDoc`.`en`.`coat-of-arms`) LIKE LOWER(@' . $bindKeys[1] + . ')) RETURN houseDoc', + $query->toSql(), + ); + + $results = $query->get(); + expect($results->count())->toBe(2); + expect(($results->first())->name)->toBe('Lannister'); +});