问题
In Eloquent, I'd like to generate this query:
SELECT * FROM table WHERE a=1 AND ( b=2 OR c=3 );
But I seem to be generating this query instead:
SELECT * FROM table WHERE a=1 AND b=2 OR c=3;
Here is my implementation and code:
$result = Model::aIsOne()->bIsTwoOrCIsThree()->get();
Model
contains:
function scopeAIsOne($query) {
return $query->where('a', 1);
}
function scopeBIsTwoOrCIsThree($query) {
return $query->where('b', 2)->orWhere('c', 3);
}
Thanks for any help. I've searched through the docs including Advanced Wheres to no avail.
回答1:
Did you test whereRaw()?
so your function should look like:
function scopeIsFeaturedOrIsBlogPost($query) {
return $query->whereRaw('( isFeatured = "true" OR type = "blogPost" )');
}
ps. this is untested
回答2:
You can generate parentheses by passing a callback function to where()
.
Model::where('a',1)->where(function($query) {
$query->where('b', 2)->orWhere('c',3);
})->get();
回答3:
SEE EDIT FOR FINAL ANSWER
Better than raw, use orWhere with a closure:
$model = Model::whereAIsOne()->orWhere(function($query) {
$query->where('b', 1)->where('c', 1);
})->get();
The really unfortunate thing (and the way I ended up at this post) is that the second $query used in the closure is an instance of \Illuminate\Database\Query\Builder rather than \Illuminate\Database\Eloquent\Builder - this means that you can't use the model scopes within that closure, because Query\Builder instances don't have a reference to a model.
That said, I still think this is much more ORM-like and useful as a developer.
EDIT
Took a while to figure out, but this will work if you want to use your scopes as well:
$model = Model::whereAIsOne()->orWhere(function($query) {
$this->newEloquentBuilder($query)->setModel($this)->whereBIsOneAndCIsOne();
})->get();
I'm actually creating a fourth scope in my code that encompasses all of this, so the $this
might not work in this context - however, I find that scoping for my models is one of the most important parts of building a good system.
This definitely should be built into Eloquent - the engine has a good start, but so many features are missing.
回答4:
I'm a little late to the party, but wouldn't the most logical way be to wrap the where in a Closure?
Model::where('a', '=', 1)
->where(function($query) {
$query->where('b', '=', 2)
->orWhere('c', '>', 3);
})
->get();
来源:https://stackoverflow.com/questions/20914650/how-do-you-wrap-laravel-eloquent-orm-query-scopes-in-parentheses-when-chaining