Skip to content

Commit

Permalink
Improvements whereLike
Browse files Browse the repository at this point in the history
  • Loading branch information
ricardogobbosouza committed Sep 28, 2022
1 parent 0be9546 commit 0a45721
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 41 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,18 @@ $query->whereLike('title', 'john')->get();
// Returns all results where title includes `john`
```

```php
$query->whereLike('title', 'john', false)->get();

// Returns all results where title ends with `john`
```

```php
$query->whereLike('title', 'john', true, false)->get();

// Returns all results where title starts with `john`
```

You can also supply an array of columns to search in:
```php
$query->whereLike(['title', 'contact.name'], 'john')->get();
Expand Down
5 changes: 1 addition & 4 deletions src/Macros/Filter.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

namespace Datalogix\BuilderMacros\Macros;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Arr;

/**
Expand All @@ -17,9 +16,7 @@ public function __invoke()
{
return function ($filters) {
foreach (Arr::wrap($filters) as $column => $filter) {
$this->when($filter, function (Builder $query, $filter) use ($column) {
return $query->whereLike($column, $filter);
});
$this->whereLike($column, $filter);
}

return $this;
Expand Down
67 changes: 37 additions & 30 deletions src/Macros/WhereLike.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,40 +17,47 @@ class WhereLike
{
public function __invoke()
{
return function ($columns, $value) {
$this->where(function (Builder $query) use ($columns, $value) {
foreach (Arr::wrap($columns) as $column) {
$query->when(
Str::contains($column, '.'),

// Relational searches
function (Builder $query) use ($column, $value) {
$parts = explode('.', $column);
$relationColumn = array_pop($parts);
$relationName = join('.', $parts);

return $query->orWhereHas(
$relationName,
function (Builder $query) use ($relationColumn, $value) {
if (Str::endsWith($relationColumn, '_id')) {
$query->where($relationColumn, $value);
} else {
$query->where($relationColumn, 'LIKE', "%{$value}%");
return function ($columns, $value, $start = true, $end = true) {
$start = $start === true ? '%' : $start;
$end = $end === true ? '%' : $end;

$this->when(filled($value), function (Builder $query) use ($columns, $value, $start, $end) {
return $query->where(function (Builder $query) use ($columns, $value, $start, $end) {
$from = $query->getQuery()->from;

foreach (Arr::wrap($columns) as $column) {
$query->when(
Str::contains($column, '.'),

// Relational searches
function (Builder $query) use ($column, $value, $start, $end) {
$parts = explode('.', $column);
$relationColumn = array_pop($parts);
$relationName = join('.', $parts);

return $query->orWhereHas(
$relationName,
function (Builder $query) use ($relationColumn, $value, $start, $end) {
if (Str::endsWith($relationColumn, '_id')) {
$query->where($relationColumn, $value);
} else {
$query->where($relationColumn, 'LIKE', $start.$value.$end);
}
}
);
},

// Default searches
function (Builder $query) use ($from, $column, $value, $start, $end) {
if (Str::endsWith($column, '_id')) {
return $query->orWhere(($from ? $from.'.' : '').$column, $value);
}
);
},

// Default searches
function (Builder $query) use ($column, $value) {
if (Str::endsWith($column, '_id')) {
return $query->orWhere($column, $value);
return $query->orWhere(($from ? $from.'.' : '').$column, 'LIKE', $start.$value.$end);
}

return $query->orWhere($column, 'LIKE', "%{$value}%");
}
);
}
);
}
});
});

return $this;
Expand Down
6 changes: 3 additions & 3 deletions tests/Macros/FilterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,23 @@ class FilterTest extends TestCase
{
public function testQueryWithOneColumn()
{
$expected = 'select * from "users" where ("name" LIKE ?)';
$expected = 'select * from "users" where ("users"."name" LIKE ?)';
$actual = User::filter(['name' => 'foo'])->toSql();

$this->assertEquals($expected, $actual);
}

public function testQueryWithMoreColumns()
{
$expected = 'select * from "users" where ("name" LIKE ?) and ("email" LIKE ?)';
$expected = 'select * from "users" where ("users"."name" LIKE ?) and ("users"."email" LIKE ?)';
$actual = User::filter(['name' => 'foo', 'email' => 'foo'])->toSql();

$this->assertEquals($expected, $actual);
}

public function testQueryWithColumnNullable()
{
$expected = 'select * from "users" where ("name" LIKE ?)';
$expected = 'select * from "users" where ("users"."name" LIKE ?)';
$actual = User::filter(['name' => 'foo', 'email' => null])->toSql();

$this->assertEquals($expected, $actual);
Expand Down
20 changes: 16 additions & 4 deletions tests/Macros/WhereLikeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,45 @@

class WhereLikeTest extends TestCase
{
public function testQueryWithBlankValue()
{
$this->assertEquals('select * from "users"', User::whereLike('name', null)->toSql());
$this->assertEquals('select * from "users"', User::whereLike('name', '')->toSql());
}

public function testQueryWithFilledValue()
{
$this->assertEquals('select * from "users" where ("users"."name" LIKE ?)', User::whereLike('name', false)->toSql());
$this->assertEquals('select * from "users" where ("users"."name" LIKE ?)', User::whereLike('name', 0)->toSql());
}

public function testQueryWithOneColumn()
{
$expected = 'select * from "users" where ("name" LIKE ?)';
$expected = 'select * from "users" where ("users"."name" LIKE ?)';
$actual = User::whereLike('name', 'foo')->toSql();

$this->assertEquals($expected, $actual);
}

public function testQueryWithMoreColumns()
{
$expected = 'select * from "users" where ("name" LIKE ? or "email" LIKE ?)';
$expected = 'select * from "users" where ("users"."name" LIKE ? or "users"."email" LIKE ?)';
$actual = User::whereLike(['name', 'email'], 'foo')->toSql();

$this->assertEquals($expected, $actual);
}

public function testQueryWithRelation()
{
$expected = 'select * from "users" where ("name" LIKE ? or "email" LIKE ? or exists (select * from "posts" where "users"."id" = "posts"."user_id" and "title" LIKE ?))';
$expected = 'select * from "users" where ("users"."name" LIKE ? or "users"."email" LIKE ? or exists (select * from "posts" where "users"."id" = "posts"."user_id" and "title" LIKE ?))';
$actual = User::whereLike(['name', 'email', 'posts.title'], 'foo')->toSql();

$this->assertEquals($expected, $actual);
}

public function testQueryWithColumnKey()
{
$expected = 'select * from "users" where ("name_id" = ?)';
$expected = 'select * from "users" where ("users"."name_id" = ?)';
$actual = User::whereLike(['name_id'], 'foo')->toSql();

$this->assertEquals($expected, $actual);
Expand Down

0 comments on commit 0a45721

Please sign in to comment.