Skip to content

Instantly share code, notes, and snippets.

@yavgel85
Last active June 14, 2022 14:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yavgel85/d1d69b0f1cfde5a2a2e7c0733a585400 to your computer and use it in GitHub Desktop.
Save yavgel85/d1d69b0f1cfde5a2a2e7c0733a585400 to your computer and use it in GitHub Desktop.
whereLike macro #laravel #queryBuilder #macro
// 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