I want to filter products by category (manyToMany relationship). Basically the user select which categories to show. The categories I want to filter are in $request->keywords. This is what I tried:
$products = Product::all();
foreach($request->keywords as $keyword) {
$products = Product::whereHas('categories', function($q) use ($keyword){
$q->where('title', '=', $keyword);
})->get();
}
return response()->json($products);
The problem is that this does not get all the categories, only the products with the last category in the array. I guess at this point: $q->where('title', '=', $keyword);, $q does not keep the results of the last loop iteration but always deletes the last loop results.
I also tried the same thing with $q->orWhere('title', '=', $keyword);, but that actually doesn't give me any results.
Thanks for your help!
Changed your approach to fetch the data,
$products = Product::all();
if (!empty($request->keywords)) { // if keywords not empty
$keyword = $request->keywords;
$products = Product::whereHas('categories', function ($q) use ($keyword) {
$q->whereIn('title', $keyword); // where in for array
})->get(); // it won't override old data as there is no loop
}
return response()->json($products);
You can simply use whereIn on the title field by passing in your keywords.
$products = Product::all();
$titles = [];
foreach($request->keywords as $keyword) {
$titles[] = $keyword;
}
$products = Product::whereHas('categories', function($q) use ($keyword){
$q->whereIn('title', $titles);
})->get();
I'm improving other persons answer. Below is the filtered code here
$builder = new Product;
if($request->filled('keywords')) { // if keywords key has any value then query will execute.
$builder = $builder->whereHas('categories', function($q) use ($request){
$q->whereIn('title', array_values($request->keywords));
});
}
$items = $builder->get();
dd($items);
You can try this.
Related
lets say I have a collection of users Users::all()
I would like to take sort/order it like such Users::all()->sort('created_at', 'DESC')
then I would like to sub order it by an array like [1,5,3,9,4,8] so perhpas a call like this Users::all()->sort('created_at', 'DESC')->sortBy("id", [1,5,3,9,4,8])
Any Advice?
Edit 1
I have found this, is this correct to use?
$ids = collect([1,5,3,9,4,8]);
$users = Users::all()->sort('created_at', 'DESC');
$users = $ids->map(function($id) use($users) {
return $users->where('cat_id', $id)->first();
});
I think you could just invoke orderBy() twice.
$ids = [1,5,3,9,4,8];
$users = Users::all()
->orderBy('created_at', 'desc')
->orderBy($ids)
->get();
Does this answer your question?
You can use whereIn like this probably:
$ids = [1,5,3,9,4,8];
$users = Users::all()
->orderBy('created_at', 'desc')
->whereIn('cat_id', $ids)
->get();
https://laravel.com/docs/9.x/queries#additional-where-clauses
The whereIn method verifies that a given column's value is contained within the given array
So I found a solution.
$ids = json_decode($interview->question_ids ?? '[]');
if(count($ids) == 0){ // if empty create new id array and save to DB
$ids = collect(questions::all()->where('interview_id', $interview->id)->pluck('id')->toArray());
$interview->question_ids = json_encode($ids);
$interview->save();
}
$questions = questions::all()->where('interview_id', $interview->id)->sortBy([
['order_timestamp', 'asc'],
['created_at', 'asc'],
]);
$questions = $ids->map(function($id) use($questions) {
return $questions->where('id', $id)->first();
});
$questions = $questions->flatten();
How to delete the item when products[] is empty?
This is how I get it from the database:
$orders = Order::with(['order_details.products' => function($q) use ($place) {
$categories = Categorie::where('place', $place)->get();
$validCategories = [];
foreach ($categories as $categorie){
array_push($validCategories, $categorie->id);
}
$q->where('products.categorie_id', '=', $validCategories);
}])->get();
and this is the result: Result
But I only want the items if products[] is not empty. How can I do that?
for example here: example
Here are the products empty but now I want to remove all this data.
You could attempt to filter the eager load using with with a callback and using a whereHas with the same callback to remove the unneeded order_details.
Try something like this:
$catIds = Categorie::where('place', $place)->pluck('id');
$orders = Order::with(['order_details' => function ($q) use ($catIds) {
$q->whereHas(['products' => $func = function ($q) use ($catIds) {
$q->whereIn('categorie_id', $catIds)
})->with(['products' => $func]);
}])->get();
If not you can iterate through your collection and remove the unneeded records.
I am having problem to count number of devices where guid is not null.
It need to get all the shops by user user_id and then count all the devices where guid is not null.
$shops = Shop::with('devices')->where('user_id', $userId)->get();
$deviceActive = $shops->reduce(function ($carry, $item) {
return $carry + $item->devices->whereNotNull('guid')->count();
});
dd($deviceActive );
It work when I do:
return $carry + $item->devices->count();
but it need to count where guid is not null.
I would also be interested to hear if there is alternative reduce approach.
Since $item->devices is a collection there is no whereNotNull() for collections. So try to use where():
$item->devices->where('guid', '<>', null)->count();
Try:
$shops = Shop::with('devices')
->where('user_id', $userId)
->where('guid', '!=', null)->get();
$get_count = count($shops); // it return how many values have $shops
OR
$shops= DB::table('devices')->where('user_id', $userId)
->where('guid', '!=', null)->get();
$get_count = count($shops);
if you did not have the class DB add at your controller:
use DB;
I'm trying to execute IN statement in Eloquent query. I tried this:
$id = urldecode($id);
$news = News::whereHas('newsCategories', function($q) use($id)
{
$q->where('category_id', 'IN', '('.$id.')')->orderBy('created_at', 'desc');
})->get();
But I get empty result.
When I switch IN for = and pass a number instead of array I get results. Did I do something wrong?
So this works:
$id = 2;
$news = News::whereHas('newsCategories', function($q) use($id)
{
$q->where('category_id', '=', $id)->orderBy('created_at', 'desc');
})->get();
You want whereIn with an array of your ids to be checked...
$news = News::whereHas('newsCategories', function($q) use($array_of_ids)
{
$q->whereIn('category_id', $array_of_ids)
->orderBy('created_at', 'desc');
})->get();
Just make sure that you're passing in something that is truly an array :)
I'm trying to break up an Eloquent query like this
$query = new Product;
if (!empty($req->query['id'])) {
$query->where('id', '=', '1');
}
$products = $query->get();
The result above gives me all products in the database. This however, does in fact work.
$products = Product::where('id', '=', '1')->get();
Is there a way to do this?
In Laravel 4 you need to append your query parameters to your query variable. In Laravel 3, it would work like you're doing.
This is what you need to do (I'm unsure if it will work with new Product tho):
$query = new Product;
if (!empty($req->query['id'])) {
$query = $query->where('id', '=', '1');
}
$products = $query->get();
Your code does not make sense. If you make a new Product - then it will never have an ID associated with it - so your if (!empty($req->query['id'])) will always be false.
Are you just trying to get a specific product idea?
$products = Product::find(1);
is the same as
$products = Product::where('id', '=', '1')->get();