Last active
August 3, 2017 14:24
-
-
Save FatBoyXPC/b99c0c1f545dc6e12129becf5d0970b9 to your computer and use it in GitHub Desktop.
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
<?php | |
namespace App\Traits\Database; | |
trait MaybeTrait | |
{ | |
/** | |
* I found myself doing something similar to this: | |
* $results = Company::where('type', $type) | |
* | |
* if ($region) { | |
* $results->where('region', $region) | |
* } | |
* | |
* $results->get(); | |
* | |
* But that lends itself to the when() method: | |
* | |
* Company::where('type', $type) | |
* ->when($region, function ($query) { | |
* $query->where('region', $region); | |
* }) | |
* ->get(); | |
* | |
* However, I'm not a fan of that boilerplate for every "maybe". With this | |
* trait, we can instead do this: | |
* | |
* Company::where('type', $type) | |
* ->maybeWhere($region, 'region', $region) | |
* ->get(); | |
* | |
* Where the first param when calling a "maybe" method is a predicate | |
* function. | |
*/ | |
protected function maybeScope($query, $predicate, $method, $args) | |
{ | |
return $query->when($predicate, function ($q) use ($method, $args) { | |
return $q->{$this->maybeMethodName($method)}(...$args); | |
}); | |
} | |
protected function maybeMethodName($method) | |
{ | |
return lcfirst(str_replace('scopeMaybe', '', $method)); | |
} | |
public function scopeMaybeWhere($query, $predicate, ...$args) | |
{ | |
return $this->maybeScope($query, $predicate, __FUNCTION__, $args); | |
} | |
public function scopeMaybeOrWhere($query, $predicate, ...$args) | |
{ | |
return $this->maybeScope($query, $predicate, __FUNCTION__, $args); | |
} | |
public function scopeMaybeWhereIn($query, $predicate, ...$args) | |
{ | |
return $this->maybeScope($query, $predicate, __FUNCTION__, $args); | |
} | |
public function scopeMaybeOrWhereIn($query, $predicate, ...$args) | |
{ | |
return $this->maybeScope($query, $predicate, __FUNCTION__, $args); | |
} | |
public function scopeMaybeWhereNotIn($query, $predicate, ...$args) | |
{ | |
return $this->maybeScope($query, $predicate, __FUNCTION__, $args); | |
} | |
public function scopeMaybeOrWhereNotIn($query, $predicate, ...$args) | |
{ | |
return $this->maybeScope($query, $predicate, __FUNCTION__, $args); | |
} | |
public function scopeMaybeWhereExists($query, $predicate, ...$args) | |
{ | |
return $this->maybeScope($query, $predicate, __FUNCTION__, $args); | |
} | |
public function scopeMaybeWhereNotExists($query, $predicate, ...$args) | |
{ | |
return $this->maybeScope($query, $predicate, __FUNCTION__, $args); | |
} | |
public function scopeMaybeOrWhereExists($query, $predicate, ...$args) | |
{ | |
return $this->maybeScope($query, $predicate, __FUNCTION__, $args); | |
} | |
public function scopeMaybeOrWhereNotExists($query, $predicate, ...$args) | |
{ | |
return $this->maybeScope($query, $predicate, __FUNCTION__, $args); | |
} | |
public function scopeMaybeWhereBetween($query, $predicate, ...$args) | |
{ | |
return $this->maybeScope($query, $predicate, __FUNCTION__, $args); | |
} | |
public function scopeMaybeWhereNotBetween($query, $predicate, ...$args) | |
{ | |
return $this->maybeScope($query, $predicate, __FUNCTION__, $args); | |
} | |
public function scopeMaybeOrWhereBetween($query, $predicate, ...$args) | |
{ | |
return $this->maybeScope($query, $predicate, __FUNCTION__, $args); | |
} | |
public function scopeMaybeOrWhereNotBetween($query, $predicate, ...$args) | |
{ | |
return $this->maybeScope($query, $predicate, __FUNCTION__, $args); | |
} | |
public function scopeMaybeWhereNull($query, $predicate, ...$args) | |
{ | |
return $this->maybeScope($query, $predicate, __FUNCTION__, $args); | |
} | |
public function scopeMaybeWhereNotNull($query, $predicate, ...$args) | |
{ | |
return $this->maybeScope($query, $predicate, __FUNCTION__, $args); | |
} | |
public function scopeMaybeOrWhereNull($query, $predicate, ...$args) | |
{ | |
return $this->maybeScope($query, $predicate, __FUNCTION__, $args); | |
} | |
public function scopeMaybeOrWhereNotNull($query, $predicate, ...$args) | |
{ | |
return $this->maybeScope($query, $predicate, __FUNCTION__, $args); | |
} | |
public function scopeMaybeWhereColumn($query, $predicate, ...$args) | |
{ | |
return $this->maybeScope($query, $predicate, __FUNCTION__, $args); | |
} | |
public function scopeMaybeOrWhereColumn($query, $predicate, ...$args) | |
{ | |
return $this->maybeScope($query, $predicate, __FUNCTION__, $args); | |
} | |
public function scopeMaybeWhereDate($query, $predicate, ...$args) | |
{ | |
return $this->maybeScope($query, $predicate, __FUNCTION__, $args); | |
} | |
public function scopeMaybeWhereTime($query, $predicate, ...$args) | |
{ | |
return $this->maybeScope($query, $predicate, __FUNCTION__, $args); | |
} | |
public function scopeMaybeOrWhereDate($query, $predicate, ...$args) | |
{ | |
return $this->maybeScope($query, $predicate, __FUNCTION__, $args); | |
} | |
public function scopeMaybeOrWhereTime($query, $predicate, ...$args) | |
{ | |
return $this->maybeScope($query, $predicate, __FUNCTION__, $args); | |
} | |
public function scopeMaybeWhereDay($query, $predicate, ...$args) | |
{ | |
return $this->maybeScope($query, $predicate, __FUNCTION__, $args); | |
} | |
public function scopeMaybeWhereMonth($query, $predicate, ...$args) | |
{ | |
return $this->maybeScope($query, $predicate, __FUNCTION__, $args); | |
} | |
public function scopeMaybeWhereYear($query, $predicate, ...$args) | |
{ | |
return $this->maybeScope($query, $predicate, __FUNCTION__, $args); | |
} | |
} |
Thanks for looking! Interestingly enough, most of these points are answered just by understanding how Laravel does query scopes.
- When you create a query scope in laravel, you prepend the method name with
scope
. - All of the methods I defined here are the (what I consider) relevant
where()
methods that exist on a Query Builder object. I ignored thewhere
methods that were for sub-selects as I feel like that is a different context. I can't imagine people often want to use a sub-select on a model, and query scopes only apply to models. - All of the
where
methods default toand
, and all of theorWhere
methods just call the equivalentwhere
method with the$boolean
param set toor
. This is just how Laravel set's it up! The same idea applies for the(or)whereNot
methods. All of these query scope methods are chainable! - No tests here because this was just to show the concept and the implementation :P But this is a very valid point!
- Point taken. Sadly not that familiar with Laravel's query engine :(.
- Well stated.
- :/ Wish Yii did this...
- ;)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Interesting. Couple observations:
scope
, why? Using the traits methods the user know's it is a scope centric method.Suggestion: Remove
scope
from method names.andMaybeWhere
that is a facade formaybeWhere
as many AR/ORM libraries allow chaining of the where clauses....also, and more importantly....