How to use a list of IDs in a query - php

I have a query that filter users to display to admins by ID, now I would like to expand this query to accommodate more IDs like 2,3,4,5 and 6, so how do I arrange it in a list
public function vipusers()
{
$data['title'] = 'Vip Users';
$is_super = !auth()->guard('admin')->user()->is_super;
$data['users'] = Users::when($is_super, function ($q) {
$q->where('id', '!=', 1);
})
->orderBy('id', 'DESC')->get();
return view('admin.dashboard.manage', $data);
}

You can use whereIn :
https://laravel.com/docs/8.x/queries#additional-where-clauses
$ids = [2, 3, 4, 5, 6];
$users = Users::whereIn('id', $ids)->orderBy('id', 'DESC')->get();
...

Extending #Bazaim's answer.
Consider using a function to iterate through all the users, by passing the id from table to the function. Consider using the following snippet.
public function vipusers($id)
{
$data['title'] = 'Vip Users';
$is_super = !auth()->guard('admin')->user()->is_super;
$data['users'] = Users::when($is_super, function ($q) {
$q->where('id', '!=', $id);
})->orderBy('id', 'DESC')->get();
return view('admin.dashboard.manage', $data);
}

This solved what I'm trying to achieve according to https://laravel.com/docs/8.x/queries#where-clauses
public function vipusers()
{
$data['title'] = 'Vip Users';
$is_super = !auth()->guard('admin')->user()->is_super;
$data['users'] = Users::when($is_super, function ($q) {
$q->where('id', '!=', 1)
->where('id', '!=', 2)
->where('id', '!=', 3);
})
->orderBy('id', 'DESC')->get();
return view('admin.dashboard.manage', $data);
}

Related

Laravel whereHas and for each of collection

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

Laravel nested relation filter

Have a query, how I can filter results by translation relation (by name column)
$item = Cart::select('product_id','quantity')
->with(['product.translation:product_id,name','product.manufacturer:id,name'])
->where($cartWhere)
->get();
my model
Cart.php
public function product($language = null)
{
return $this->hasOne('App\Models\Product','id','product_id');
}
Product.php
public function translations()
{
return $this->hasMany('App\Models\ProductTranslation','product_id','id');
}
Update v1.0
do like this, but query takes too long time
$item = Cart::select('product_id','quantity')
->with(['product.translation', 'product.manufacturer:id,name'])
->where($cartWhere)
->when($search,function ($q) use ($search) {
$q->whereHas('product.translation', function (Builder $query) use ($search) {
$query->where('name', 'like', '%'.$search.'%');
$query->select('name');
});
}
)
->get() ;
Inside the array within your with() method, you can pass a function as a value.
Cart::select('product_id','quantity')
->with([
'product', function($query) {
$query->where($filteringAndConditionsHere);
}
]);
https://laravel.com/docs/7.x/eloquent-relationships#eager-loading

Laravel and Eloquent - applying different filters

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();;

Laravel belongsToMany with OR condition

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.

Laravel 5.2 query 1 table for postcode then grab ids and query another

I am trying to learn how to do a query. the search field is for postcodes which are stored inside of user_profiles (and user_profiles have a relationship with users)
So I have something that returns one result (however there are more than 1) but I heard doing 2 query's for one is bad
public function index()
{
$queryUsername = Request::get('username');
$queryPostcode = Request::get('postcode');
if ($queryUsername) {
$users = User::where('username', 'LIKE', "%$queryUsername%")->get();
}
if ($queryPostcode) {
$usersInfo = UserProfile::where('postcode', '=', "$queryPostcode")->value('user_id');
$users = User::where('id', '=', "$usersInfo")->get();
}
return view('view', compact('users'));
}
for the question referenced better way is to go with join instead of two different queries
public function index()
{
$queryUsername = Request::get('username');
$queryPostcode = Request::get('postcode');
if ($queryUsername) {
$users = User::where('username', 'LIKE', "%$queryUsername%")->get();
}
if ($queryPostcode) {
$users = Users::rightJoin('user_profiles','users.id', '=', 'user_profiles.user_id')
->where('user_profiles.postcode', '=', "$queryPostcode")
->select(\DB::raw('users.*'))
->get();
}
return view('view', compact('users'));
}
if you are looking for an exact match of username
its not good to use LIKE for username matching
$users = User::where('username', 'LIKE', "%$queryUsername%")->get();
because for usernames chris and chrisgeorge and christy the query %chris% will work and you wont get the exact match so recommend to use '=' instead of like
Try with this:
public function index(){
$queryUsername = Request::get('username');
$queryPostcode = Request::get('postcode');
if ($queryUsername):
$users = User::where('username', 'LIKE', "%".$queryUsername."%")->get();
elseif ($queryPostcode):
$usersInfo = UserProfile::where('postcode', '=', $queryPostcode)->value('user_id');
$users = User::where('id', '=', "$usersInfo")->get();
endif;
return view('view', compact('users'));
}

Categories