Skip to content

Commit 95107a0

Browse files
Add whereLike clause to query builder (#52147)
* Add database grammer for whereLike method * Add whereLike to database query builder * Add whereLike clause to MySQL grammar * Add whereLike clause to Postgres grammar * Add whereLike clause to SQLite grammar * Add whereLike query builder test for sql server * Run whereLike integration test on all databases * Skip sqlsrv where like integration test * Fic styling * formatting --------- Co-authored-by: Taylor Otwell <[email protected]>
1 parent 92a78ce commit 95107a0

File tree

7 files changed

+380
-0
lines changed

7 files changed

+380
-0
lines changed

src/Illuminate/Database/Query/Builder.php

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,6 +1121,71 @@ public function orWhereRaw($sql, $bindings = [])
11211121
return $this->whereRaw($sql, $bindings, 'or');
11221122
}
11231123

1124+
/**
1125+
* Add a "where like" clause to the query.
1126+
*
1127+
* @param string $column
1128+
* @param string $value
1129+
* @param bool $caseSensitive
1130+
* @param string $boolean
1131+
* @param bool $not
1132+
* @return $this
1133+
*/
1134+
public function whereLike($column, $value, $caseSensitive = false, $boolean = 'and', $not = false)
1135+
{
1136+
$type = 'Like';
1137+
1138+
$this->wheres[] = compact('type', 'column', 'value', 'caseSensitive', 'boolean', 'not');
1139+
1140+
if (method_exists($this->grammar, 'prepareWhereLikeBinding')) {
1141+
$value = $this->grammar->prepareWhereLikeBinding($value, $caseSensitive);
1142+
}
1143+
1144+
$this->addBinding($value);
1145+
1146+
return $this;
1147+
}
1148+
1149+
/**
1150+
* Add an "or where like" clause to the query.
1151+
*
1152+
* @param string $column
1153+
* @param string $value
1154+
* @param bool $caseSensitive
1155+
* @return $this
1156+
*/
1157+
public function orWhereLike($column, $value, $caseSensitive = false)
1158+
{
1159+
return $this->whereLike($column, $value, $caseSensitive, 'or', false);
1160+
}
1161+
1162+
/**
1163+
* Add a "where not like" clause to the query.
1164+
*
1165+
* @param string $column
1166+
* @param string $value
1167+
* @param bool $caseSensitive
1168+
* @param string $boolean
1169+
* @return $this
1170+
*/
1171+
public function whereNotLike($column, $value, $caseSensitive = false, $boolean = 'and')
1172+
{
1173+
return $this->whereLike($column, $value, $caseSensitive, $boolean, true);
1174+
}
1175+
1176+
/**
1177+
* Add an "or where not like" clause to the query.
1178+
*
1179+
* @param string $columns
1180+
* @param string $value
1181+
* @param bool $caseSensitive
1182+
* @return $this
1183+
*/
1184+
public function orWhereNotLike($column, $value, $caseSensitive = false)
1185+
{
1186+
return $this->whereNotLike($column, $value, $caseSensitive, 'or');
1187+
}
1188+
11241189
/**
11251190
* Add a "where in" clause to the query.
11261191
*

src/Illuminate/Database/Query/Grammars/Grammar.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,24 @@ protected function whereBitwise(Builder $query, $where)
308308
return $this->whereBasic($query, $where);
309309
}
310310

311+
/**
312+
* Compile a "where like" clause.
313+
*
314+
* @param \Illuminate\Database\Query\Builder $query
315+
* @param array $where
316+
* @return string
317+
*/
318+
protected function whereLike(Builder $query, $where)
319+
{
320+
if ($where['caseSensitive']) {
321+
throw new RuntimeException('This database engine does not support case sensitive like operations.');
322+
}
323+
324+
$where['operator'] = $where['not'] ? 'not like' : 'like';
325+
326+
return $this->whereBasic($query, $where);
327+
}
328+
311329
/**
312330
* Compile a "where in" clause.
313331
*

src/Illuminate/Database/Query/Grammars/MySqlGrammar.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,22 @@ class MySqlGrammar extends Grammar
1515
*/
1616
protected $operators = ['sounds like'];
1717

18+
/**
19+
* Compile a "where like" clause.
20+
*
21+
* @param \Illuminate\Database\Query\Builder $query
22+
* @param array $where
23+
* @return string
24+
*/
25+
protected function whereLike(Builder $query, $where)
26+
{
27+
$where['operator'] = $where['not'] ? 'not ' : '';
28+
29+
$where['operator'] .= $where['caseSensitive'] ? 'like binary' : 'like';
30+
31+
return $this->whereBasic($query, $where);
32+
}
33+
1834
/**
1935
* Add a "where null" clause to the query.
2036
*

src/Illuminate/Database/Query/Grammars/PostgresGrammar.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,22 @@ protected function whereBitwise(Builder $query, $where)
6868
return '('.$this->wrap($where['column']).' '.$operator.' '.$value.')::bool';
6969
}
7070

71+
/**
72+
* Compile a "where like" clause.
73+
*
74+
* @param \Illuminate\Database\Query\Builder $query
75+
* @param array $where
76+
* @return string
77+
*/
78+
protected function whereLike(Builder $query, $where)
79+
{
80+
$where['operator'] = $where['not'] ? 'not ' : '';
81+
82+
$where['operator'] .= $where['caseSensitive'] ? 'like' : 'ilike';
83+
84+
return $this->whereBasic($query, $where);
85+
}
86+
7187
/**
7288
* Compile a "where date" clause.
7389
*

src/Illuminate/Database/Query/Grammars/SQLiteGrammar.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,39 @@ protected function wrapUnion($sql)
4242
return 'select * from ('.$sql.')';
4343
}
4444

45+
/**
46+
* Compile a "where like" clause.
47+
*
48+
* @param \Illuminate\Database\Query\Builder $query
49+
* @param array $where
50+
* @return string
51+
*/
52+
protected function whereLike(Builder $query, $where)
53+
{
54+
if ($where['caseSensitive'] == false) {
55+
return parent::whereLike($query, $where);
56+
}
57+
$where['operator'] = $where['not'] ? 'not glob' : 'glob';
58+
59+
return $this->whereBasic($query, $where);
60+
}
61+
62+
/**
63+
* Convert a LIKE pattern to a GLOB pattern using simple string replacement.
64+
*
65+
* @param string $value
66+
* @param bool $caseSensitive
67+
* @return string
68+
*/
69+
public function prepareWhereLikeBinding($value, $caseSensitive)
70+
{
71+
return $caseSensitive === false ? $value : str_replace(
72+
['*', '?', '%', '_'],
73+
['[*]', '[?]', '*', '?'],
74+
$value
75+
);
76+
}
77+
4578
/**
4679
* Compile a "where date" clause.
4780
*

tests/Database/DatabaseQueryBuilderTest.php

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,128 @@ public function testWhereLikePostgres()
656656
$this->assertEquals([0 => '1'], $builder->getBindings());
657657
}
658658

659+
public function testWhereLikeClausePostgres()
660+
{
661+
$builder = $this->getPostgresBuilder();
662+
$builder->select('*')->from('users')->whereLike('id', '1');
663+
$this->assertSame('select * from "users" where "id"::text ilike ?', $builder->toSql());
664+
$this->assertEquals([0 => '1'], $builder->getBindings());
665+
666+
$builder = $this->getPostgresBuilder();
667+
$builder->select('*')->from('users')->whereLike('id', '1', false);
668+
$this->assertSame('select * from "users" where "id"::text ilike ?', $builder->toSql());
669+
$this->assertEquals([0 => '1'], $builder->getBindings());
670+
671+
$builder = $this->getPostgresBuilder();
672+
$builder->select('*')->from('users')->whereLike('id', '1', true);
673+
$this->assertSame('select * from "users" where "id"::text like ?', $builder->toSql());
674+
$this->assertEquals([0 => '1'], $builder->getBindings());
675+
676+
$builder = $this->getPostgresBuilder();
677+
$builder->select('*')->from('users')->whereNotLike('id', '1');
678+
$this->assertSame('select * from "users" where "id"::text not ilike ?', $builder->toSql());
679+
$this->assertEquals([0 => '1'], $builder->getBindings());
680+
681+
$builder = $this->getPostgresBuilder();
682+
$builder->select('*')->from('users')->whereNotLike('id', '1', false);
683+
$this->assertSame('select * from "users" where "id"::text not ilike ?', $builder->toSql());
684+
$this->assertEquals([0 => '1'], $builder->getBindings());
685+
686+
$builder = $this->getPostgresBuilder();
687+
$builder->select('*')->from('users')->whereNotLike('id', '1', true);
688+
$this->assertSame('select * from "users" where "id"::text not like ?', $builder->toSql());
689+
$this->assertEquals([0 => '1'], $builder->getBindings());
690+
}
691+
692+
public function testWhereLikeClauseMysql()
693+
{
694+
$builder = $this->getMySqlBuilder();
695+
$builder->select('*')->from('users')->whereLike('id', '1');
696+
$this->assertSame('select * from `users` where `id` like ?', $builder->toSql());
697+
$this->assertEquals([0 => '1'], $builder->getBindings());
698+
699+
$builder = $this->getMySqlBuilder();
700+
$builder->select('*')->from('users')->whereLike('id', '1', false);
701+
$this->assertSame('select * from `users` where `id` like ?', $builder->toSql());
702+
$this->assertEquals([0 => '1'], $builder->getBindings());
703+
704+
$builder = $this->getMySqlBuilder();
705+
$builder->select('*')->from('users')->whereLike('id', '1', true);
706+
$this->assertSame('select * from `users` where `id` like binary ?', $builder->toSql());
707+
$this->assertEquals([0 => '1'], $builder->getBindings());
708+
709+
$builder = $this->getMySqlBuilder();
710+
$builder->select('*')->from('users')->whereNotLike('id', '1');
711+
$this->assertSame('select * from `users` where `id` not like ?', $builder->toSql());
712+
$this->assertEquals([0 => '1'], $builder->getBindings());
713+
714+
$builder = $this->getMySqlBuilder();
715+
$builder->select('*')->from('users')->whereNotLike('id', '1', false);
716+
$this->assertSame('select * from `users` where `id` not like ?', $builder->toSql());
717+
$this->assertEquals([0 => '1'], $builder->getBindings());
718+
719+
$builder = $this->getMySqlBuilder();
720+
$builder->select('*')->from('users')->whereNotLike('id', '1', true);
721+
$this->assertSame('select * from `users` where `id` not like binary ?', $builder->toSql());
722+
$this->assertEquals([0 => '1'], $builder->getBindings());
723+
}
724+
725+
public function testWhereLikeClauseSqlite()
726+
{
727+
$builder = $this->getSQLiteBuilder();
728+
$builder->select('*')->from('users')->whereLike('id', '1');
729+
$this->assertSame('select * from "users" where "id" like ?', $builder->toSql());
730+
$this->assertEquals([0 => '1'], $builder->getBindings());
731+
732+
$builder = $this->getSQLiteBuilder();
733+
$builder->select('*')->from('users')->whereLike('id', '1', true);
734+
$this->assertSame('select * from "users" where "id" glob ?', $builder->toSql());
735+
$this->assertEquals([0 => '1'], $builder->getBindings());
736+
737+
$builder = $this->getSQLiteBuilder();
738+
$builder->select('*')->from('users')->whereLike('description', 'Hell* _orld?%', true);
739+
$this->assertSame('select * from "users" where "description" glob ?', $builder->toSql());
740+
$this->assertEquals([0 => 'Hell[*] ?orld[?]*'], $builder->getBindings());
741+
742+
$builder = $this->getSQLiteBuilder();
743+
$builder->select('*')->from('users')->whereNotLike('id', '1');
744+
$this->assertSame('select * from "users" where "id" not like ?', $builder->toSql());
745+
$this->assertEquals([0 => '1'], $builder->getBindings());
746+
747+
$builder = $this->getSQLiteBuilder();
748+
$builder->select('*')->from('users')->whereNotLike('description', 'Hell* _orld?%', true);
749+
$this->assertSame('select * from "users" where "description" not glob ?', $builder->toSql());
750+
$this->assertEquals([0 => 'Hell[*] ?orld[?]*'], $builder->getBindings());
751+
752+
$builder = $this->getSQLiteBuilder();
753+
$builder->select('*')->from('users')->whereLike('name', 'John%', true)->whereNotLike('name', '%Doe%', true);
754+
$this->assertSame('select * from "users" where "name" glob ? and "name" not glob ?', $builder->toSql());
755+
$this->assertEquals([0 => 'John*', 1 => '*Doe*'], $builder->getBindings());
756+
757+
$builder = $this->getSQLiteBuilder();
758+
$builder->select('*')->from('users')->whereLike('name', 'John%')->orWhereLike('name', 'Jane%', true);
759+
$this->assertSame('select * from "users" where "name" like ? or "name" glob ?', $builder->toSql());
760+
$this->assertEquals([0 => 'John%', 1 => 'Jane*'], $builder->getBindings());
761+
}
762+
763+
public function testWhereLikeClauseSqlServer()
764+
{
765+
$builder = $this->getSqlServerBuilder();
766+
$builder->select('*')->from('users')->whereLike('id', '1');
767+
$this->assertSame('select * from [users] where [id] like ?', $builder->toSql());
768+
$this->assertEquals([0 => '1'], $builder->getBindings());
769+
770+
$builder = $this->getSqlServerBuilder();
771+
$builder->select('*')->from('users')->whereLike('id', '1')->orWhereLike('id', '2');
772+
$this->assertSame('select * from [users] where [id] like ? or [id] like ?', $builder->toSql());
773+
$this->assertEquals([0 => '1', 1 => '2'], $builder->getBindings());
774+
775+
$builder = $this->getSqlServerBuilder();
776+
$builder->select('*')->from('users')->whereNotLike('id', '1');
777+
$this->assertSame('select * from [users] where [id] not like ?', $builder->toSql());
778+
$this->assertEquals([0 => '1'], $builder->getBindings());
779+
}
780+
659781
public function testWhereDateSqlite()
660782
{
661783
$builder = $this->getSQLiteBuilder();

0 commit comments

Comments
 (0)