How do I say WHERE (a = 1 OR b =1 ) AND (c = 1 OR d = 1)
For more complicated queries am I supposed to use raw SQL?
Make use of Logical Grouping (Laravel 7.x/4.2). For your example, it'd be something like this:
Model::where(function ($query) {
$query->where('a', '=', 1)
->orWhere('b', '=', 1);
})->where(function ($query) {
$query->where('c', '=', 1)
->orWhere('d', '=', 1);
});
If you want to use parameters for a,b,c,d in Laravel 4
Model::where(function ($query) use ($a,$b) {
$query->where('a', '=', $a)
->orWhere('b', '=', $b);
})
->where(function ($query) use ($c,$d) {
$query->where('c', '=', $c)
->orWhere('d', '=', $d);
});
Incase you're looping the OR conditions, you don't need the the second $query->where from the other posts (actually I don't think you need in general, you can just use orWhere in the nested where if easier)
$attributes = ['first'=>'a','second'=>'b'];
$query->where(function ($query) use ($attributes)
{
foreach ($attributes as $key=>value)
{
//you can use orWhere the first time, doesn't need to be ->where
$query->orWhere($key,$value);
}
});
if you want to use parentheses in laravel 4 and don't forget return
In Laravel 4 (at least) you need to use $a, $b in parentheses as in the example
$a = 1;
$b = 1;
$c = 1;
$d = 1;
Model::where(function ($query) use ($a, $b) {
return $query->where('a', '=', $a)
->orWhere('b', '=', $b);
})->where(function ($query) use ($c, $d) {
return $query->where('c', '=', $c)
->orWhere('d', '=', $d);
});
This is my result:
Simply Use in Laravel Eloquent:
$a='foo', $b='bar', $c='john', $d='doe';
Coder::where(function ($query) use ($a, $b) {
$query->where('a', '=', $a)
->orWhere('b', '=', $b);
})->where(function ($query) use ($c, $d) {
$query->where('c', '=', $c)
->orWhere('d', '=', $d);
})->get();
Will produce a query like:
SELECT * FROM <table> WHERE (a='foo' or b='bar') AND (c='john' or d='doe');
You can also query the first or condition and later you can apply another or condition
$model = Model::where('a',1)->orWhere('b',1);
now apply another condition on that $model variable
$model1 = $model->where('c',1)->orWhere('d',1)->get();
$a, $b, $c, $d can be dynamic values by the query
->where(function($query) use ($a, $b)
{
$query->where('a', $a)
->orWhere('b',$b);
})
->where(function($query) use ($c, $d)
{
$query->where('c', $c)
->orWhere('d',$d);
})
Another way without using Modal
Database: stocks
Columns:id,name,company_name,exchange_name,status
$name ='aa'
$stocks = DB::table('stocks')
->select('name', 'company_name', 'exchange_name')
->where(function($query) use ($name) {
$query->where('name', 'like', '%' . $name . '%')
->orWhere('company_name', 'like', '%' . $name . '%');
})
->Where('status', '=', 1)
->limit(20)
->get();
You can also use query scopes to make things a bit tidier, so you can do something like:
Invoice::where('account', 27)->notPaidAt($date)->get();
Then in your model
public function scopeNotPaidAt($query, $asAt)
{
$query = $query->where(function ($query) use ($asAt) {
$query->where('paid', '=', '0000-00-00')->orWhere('paid', '>=', $asAt);
});
return $query;
}
YourModel::where(function ($query) use($a,$b) {
$query->where('a','=',$a)
->orWhere('b','=', $b);
})->where(function ($query) use ($c,$d) {
$query->where('c','=',$c)
->orWhere('d','=',$d);
});
You can use:
Model::where('table_column', 'value')->orWhere('table_column', 'value')->get()
Best way to use sql brackets use callback function in laravel eloquent.
YourModal::where(function ($q) {
$q->where('a', 1)->orWhere('b', 1);
})->where(function ($q) {
$q->where('c', 1)->orWhere('d', 1);
});
You don't have to use = symbol, it's come as the default
Lest say if you have a query that contain brackets inside a brackets
WHERE (a = 1 OR (b = 1 and c = 5))
YourModal::where(function ($q) {
$q->where('a', 1)->orWhere(function($q2){
$q2->where('b', 1)->where('c', 5);
});
});
lest say you want to make values dynamics
YourModal::where(function ($q) use($val1, $val2) {
$q->where('a', $val1)->orWhere(function($q2) use($val2){
$q2->where('b', $val2)->where('c', $val2);
});
});
ModelName::where(function ($query) use ($a) {
$query->where('a', '=', $a)->orWhereNull('a');
})
->where(function ($query) use ($b,$c) {
$query->where('b', '=', $b)
->orWhere('c', '=', $c);
})->where('d',$d);
OUTPUT QUERY:
SELECT * FROM ModelName WHERE (a='a' or a is null) AND (b='b' or
c='c') AND d='d';
For eloquent query builder the following query will not work:
MODELNAME::where('a', 1)->orWhere('b', 1)->where('c', 1)->orWhere('d', 1);
But you can use this code:
MODELNAME::where(function($a) {
$a->where('a', 1)->orWhere('b', 1);
})->where(function($a) {
$a->where('c', 1)->orWhere('d', 1);
});
You can use the second query and it will work perfectly.
This works for me
$business = Model::where('model_id', $model_id1)->orWhere('model_id', $model_id2)->first();
Related
I would need something like this:
$user_ids = [1,2,3]; // 1 as logged user
$chats = Chat::whereHas('users', function ($q) { $q->where('users.id','=',1); })->get();
$c = null;
foreach ($chats as $chat) {
if ($chats->users->pluck('id')->diff($user_ids)->count() === 0) {
$c = $chat;
break;
}
}
return $c;
Is there some one-liner or simpler solution in laravel to get chat based on relation collection that equals to array of ids without same order within array?
If I understand you correct, you want the first chat that has exactly these user IDs right? then try this:
$user_ids = [1, 2, 3];
$chat = Chat::has('users', '=', count($user_ids))
->where(function ($query) use ($user_ids) {
foreach ($user_ids as $user_id) {
$query->whereHas('users', function ($q) use ($user_id) {
$q->where('id', $user_id);
});
}
})
->first();
$chat = Chat::whereHas('users', fn ($q) => $q->whereIn('users.id', $user_ids), '=', count($user_ids))
->whereDoesntHave('users', fn ($q) => $q->whereNotIn('users.id', $user_ids))
->first();
This works
I'm totally aware of query scopes on Eloquent and it's working fine. My problem is a bit different, this time I have one query on the DB Query Builder that contains some conditions that are repeated on other models, so I want to extract and reuse these conditions. This is my original query:
$grants = $this->grants()
->where(function ($query) use ($date) {
$query->whereDate('grant_date', '<=', $date)
->where(function ($query) use ($date) {
$query->whereNull('canceled')
->whereNull('cost');
})
->orWhere(function ($query) use ($date) {
$query->whereDate('canceled', '>', $date);
});
})
->get();
So my idea is to create a scope, let's call ActiveGrants just for the sake of the example:
public function scopeActiveGrants($query, $date)
{
return $query->where(function ($query) use ($date) {
$query->whereDate('grant_date', '<=', $date)
->where(function ($query) use ($date) {
$query->whereNull('canceled')
->whereNull('cost');
})
->orWhere(function ($query) use ($date) {
$query->whereDate('canceled', '>', $date);
});
});
}
In order to reuse the scope like this:
$grants = $this->grants()
->grantsActive()
->get();
Just a note, $this->grants() is a relationship:
public function grants()
{
return $this->hasMany(Grant::class)
}
I know Scopes work fine with Eloquent but I couldn't make work with the DB Builder. Any ideas?
Thanks in advance.
I think that I was over-engineering this code refactoring trying to things on the "Laravel" way. Nothing wrong with that, I love the framework and I like to follow its suggestion if makes sense to me. And scopes are pretty cool in my opinion.
I solved this using a regular function to return the Closure that holds all the conditions that I need:
public function activeGrants($date): Closure
{
return function ($query) use ($date) {
$query->whereDate('grant_date', '<=', $date)
->where(function ($query) use ($date) {
$query->whereNull('cancel')
->whereNull('cost');
})
->orWhere(function ($query) use ($date) {
$query->whereDate('cancel', '>', $date);
});
};
}
And then:
$this->grants()
->where($this->grantsUpTo($date))
->get();
I'm satisfied with this solution, if someone has a better idea please share o/
I am doing a filter using relations here is my controller code:
$userList = User::with(['role' ,'userMetaData','userBet','userComission','userPartnership'])
->where('deleted', '=', '0')
->when($request->parent_id, function ($builder, $parent_id) {
return $builder->where('parent_id', $parent_id);
})
->when($request->role_id, function ($builder, $role_id) {
return $builder->where('role', $role_id);
})
->when($request->to && $request->from , function ($builder) use ($request) {
return $builder->whereBetween('exposure_limit', [$request->from, $request->to]);
})
->when($request->city, function ($builder) use ($request) {
return $builder->whereHas('userMetaData', function($query) use ($request){
$query->where('city', $request->sport);
});
})
->orderBy('created_at', 'DESC')
->get();
In this case(in my code) i am trying to use whereHas() to filter a data from another table(within relations) by eloquent but it's something i am missing:
here in your case, when you use Wherehas to userMetaData it'll filter and gives you only those users who's has city as $request->sport..
In another case, you've used with('userMetaData') which means whatever users you got in filter return all userMetaData.
->when($request->city, function ($builder) use ($request) {
return $builder->whereHas('userMetaData', function($query) use ($request){
$query->where('city', $request->sport);
})->with(['userMetaData' => function($q) use ($request) {
$q->where('city', $request->sport);
}]);
})
Remove userMetaData from User::with(['role','userBet','userComission','userPartnership'])
I'm feeling stuck. :(
I want to be able to execute different SQL query, depending on the selected filters in my form:
//My initial query without any filters is this:
$dbQuery="SELECT * FROM \"interactions\" WHERE \"user_id\" = ".Auth::user()->getAttribute('id');
//Then depending on the selected filters the query may be any combination of the following:
if (request('contact_id')) $dbQuery.=" AND \"contact_id\" = ".request('contact_id');
if (request('product_id')) $dbQuery.=" AND \"product_id\" = ".request('product_id');
if (request('type')) $dbQuery.=" AND \"type\" LIKE \"%".request('type')."%\"";
if (request('description')) $dbQuery.=" AND \"description\" LIKE \"%".request('description')."%\"";
if (request('date')) $dbQuery.=" AND \"date\" >= ".request('date');
I have a class called "Interaction" which extends the Eloquent model and I need to be able to execute the above query or represent the same logic through it.
Any ideas on how I can achieve that will be greatly appreciated!
EDIT:
Thanks to Brice (my personal hero today), here is what did the trick for me:
$query = Interaction::where('user_id', Auth::id());
$contact_id = request('contact_id');
$product_id = request('product_id');
$type = request('type');
$description = request('description');
$date = request('date');
if ($contact_id) $query->where('contact_id', $contact_id);
if ($product_id) $query->where('product_id', $product_id);
if ($type) $query->where('type', 'like', "%".$type."%");
if ($description) $query->where('description', 'like', "%".$description."%");
if ($date) $query->where('date', '>=', $date);
$interactions = $query->get();
return view('interactions.index',compact('interactions'));
I'd recommend using the eloquent query builder for this.
For example:
$query = Interaction::where('user_id', Auth::id());
$contact_id = request('contact_id');
$product_id = request('product_id');
$type = request('type');
$description = request('description');
$date = request('date');
if ($contact_id) {
$query->where('contact_id', $contact_id);
}
if ($product_id) {
$query->where('product_id', $product_id);
}
if ($type) {
$query->where('type', 'like', "%$type%");
}
if ($description) {
$query->where('type', 'like', "%$description%");
}
if ($date) {
$query->where('date', '>=', \Carbon\Carbon::parse($date));
}
$results = $query->get();
If you have a lot of results, you may want to use pagination instead of fetching all results at the same time as shown above.
You can use ->when() method docs
$results = Interaction::where('user_id', Auth::id())
->when($contact_id, function ($query) use ($contact_id) {
$query->where('contact_id', $contact_id);
})
->when($product_id, function ($query) use ($product_id) {
$query->where('product_id', $product_id);
})
->when($type, function ($query) use ($type) {
$query->where('type', 'like', "%$type%");
})
->when($description, function ($query) use ($description) {
$query->where('type', 'like', "%$description%");
})
->when($date, function ($query) use ($date) {
$query->where('date', '>=', \Carbon\Carbon::parse($date));
})->get();;
How do I create brackets around my orWhere:
public function categories()
{
return $this->belongsToMany('App\Category', 'user_category')->orWhere('default', 1);
}
So it is converted to this:
where (`user_category`.`user_id` = ? or `default` = 1)
Currently the brackets here are missing and mess up the whole query. I tried for example:
public function categories()
{
$join = $this->belongsToMany('App\Category', 'user_category')
->orWhere('default', 1);
return $this->where(function ($query) use ($join) {
return $join;
});
}
But here I am loosing my model and getting Call to undefined method Illuminate\Database\Query\Builder::...
You can use advanced where clause like:
Model::where(function ($query) {
$query->where('a', '=', 1)
->orWhere('b', '=', 1);
})->where(function ($query) {
$query->where('c', '=', 1)
->orWhere('d', '=', 1);
});
Or nested clause like:
Model::where(function($query)
{
$query->where('a', 'like', 'keyword');
$query->or_where('b', 'like', 'keyword');
})
->where('c', '=', '1');
Are you trying to get all the categories related to an user and the categories where the default field is 1?
If that is the case:
public function categories()
{
return $this->belongsToMany('App\Category');
}
public function relatedCategories()
{
return App\Category::all()->where('default',1)->merge($this->categories);
}
The relatedCategories() method should return a collection with the desired categories. Take in care that the non-related categories but with default=1 will not have the pivot object, because these categories doesn't exist in your pivot table.