Last active
June 14, 2022 14:09
-
-
Save yavgel85/d1d69b0f1cfde5a2a2e7c0733a585400 to your computer and use it in GitHub Desktop.
whereLike macro #laravel #queryBuilder #macro
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Create custom method for Query Builder | |
<?php | |
// You can put it the boot method of App\Providers\AppServiceProvider or a service provider of your own. | |
//Usage Model::whereLike('name', ['mike', 'joe'])->get() | |
//Usage Model::whereLike('message.type', ['text', 'sms'])->get(); | |
Builder::macro('whereLike', function ($attributes, $terms) { | |
$this->where(function ($query) use ($attributes, $terms) { | |
foreach (array_wrap($attributes) as $attribute) { | |
// If it's a single item, wrap the value in an array e.g. $term = [$term]; | |
foreach (array_wrap($terms) as $term) { | |
// When whereLike contains a relationship.value, search the relationship value | |
$query->when(str_contains($attribute, '.'), | |
function ($query) use ($attribute, $term) { | |
[$relationName, $relationAttribute] = explode('.', $attribute); | |
// Validating if the relationship exists on the current query | |
$query->orWhereHas($relationName, function ($query) use ($relationAttribute, $term) { | |
$query->where($relationAttribute, 'LIKE', "%{$term}%"); | |
}); | |
}, | |
// A fallback for when the string DOES not contain a relationship | |
function ($query) use ($attribute, $term) { | |
$query->orWhere($attribute, 'LIKE', "%{$term}%"); | |
} | |
); | |
} | |
} | |
}); | |
// Return the $query, so you can call other methods like ->get(), ->first(), ->where(), etc | |
return $this; | |
}); | |
# 2 variant | |
# https://freek.dev/1182-searching-models-using-a-where-like-query-in-laravel#adding-support-for-relations | |
Builder::macro('whereLike', function ($attributes, string $searchTerm) { | |
$this->where(function (Builder $query) use ($attributes, $searchTerm) { | |
foreach (array_wrap($attributes) as $attribute) { | |
$query->when( | |
str_contains($attribute, '.'), | |
function (Builder $query) use ($attribute, $searchTerm) { | |
[$relationName, $relationAttribute] = explode('.', $attribute); | |
$query->orWhereHas($relationName, function (Builder $query) use ($relationAttribute, $searchTerm) { | |
$query->where($relationAttribute, 'LIKE', "%{$searchTerm}%"); | |
}); | |
}, | |
function (Builder $query) use ($attribute, $searchTerm) { | |
$query->orWhere($attribute, 'LIKE', "%{$searchTerm}%"); | |
} | |
); | |
} | |
}); | |
return $this; | |
}); | |
// Post::whereLike(['name', 'text', 'author.name', 'tags.name'], $searchTerm)->get(); | |
# 3 variant | |
# https://twitter.com/sdbruder/status/1053719431602466816?ref_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed%7Ctwterm%5E1053719431602466816%7Ctwgr%5E%7Ctwcon%5Es1_&ref_url=https%3A%2F%2Ffreek.dev%2F1182-searching-models-using-a-where-like-query-in-laraveladding-support-for-relations | |
// this version splits the search term so you can search for “Sergio Bruder” and find “Sergio Devojno Bruder”. | |
// Search terms are AND’ed per field and OR’ed between fields. so it will not find “Sergio Else” name and “bruder@email.com” mail. | |
Builder::macro('search', function ($attributes, string $searchTerms) { | |
$this->where(function (Builder $query) use ($attributes, $searchTerms) { | |
foreach (array_wrap($attributes) as $attribute) { | |
$query->orWhere(function ($query) use ($attribute, $searchTerms) { | |
foreach (explode(' ', $searchTerms) as $searchTerm) { | |
$query->where($attribute, 'LIKE', "%{$searchTerm}%"); | |
} | |
}); | |
} | |
}); | |
return $this; | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment