简体   繁体   中英

Laravel - Convert array back to a collection

I am trying to get a collection of categories only if they are in the products table. My categories table has 300 items. I only want a collection if a category is attached in the products table. The $categories collection should only result in about 10 categories because there are only about 10 products that have different category_ids

$products = DB::table('products')->groupBy('category_id')->get();

foreach($products as $product){
        $categories[] = DB::table('categories')->where('id', '=', $product->category_id)->first();
}

$categories = collect($categories)->all();

Maybe I am going about this wrong and should use a different query builder method?

The end result $categories does get the results I am after but in my blade I get the "Trying to get property of non-object" error.

If using $categories in your blade file as a collection, you will need to remove the ->all() method.

->all() is converting the collection into an array after it is being created:

$categories = collect($categories);

This can be done with one simple eloquent query. There's no need to use query builder unless you're doing something overly complex (in my opinion).

whereHas() will only return Categories that have Products.

Categories::with('products')->whereHas('products')->get();

As long as the relationships are correct on the models the above is what you're looking for. As pointed out in the comments, you need models and relationships. Laravel uses the MVC pattern, and the first letter stands for model so I'm going to guess you're using them. If not let me know and I can help set those up because you should be using them.

And if you NEED to use the query builder clean that code up and use something like this so you don't have to worry about recollecting. Also check out the hydrate() method to change these generic class instances into instances of the Categories model.

DB::table('categories')->whereIn('id', function($q){
    $q->select('category_id')->from('products');
})->get();

You get Trying to get property of non-object because one of

DB::table('categories')->where('id', '=', $product->category_id)->first();

return null value.
You can fix it this way

$products = DB::table('products')->groupBy('category_id')->get();

$categories = collect();
foreach($products as $product){
    $category = DB::table('categories')->where('id', '=', $product->category_id)->first();
    if ($category) {
        $categories->push($category); 
    }
}

If you want to get collection instance you must be use collect() helper method with array argument. For example

collect($categories); // is_array(categories) is true

You are doing many request in foreach. That is not right way. Instead it you can achieve collection instance doing only 2 request.

 $categoryIds = DB::table('products')->pluck('category_id')->toArray();
 $categories = DB::table('categories')->whereIn('id', $categoryIds)->get();

See docs https://laravel.com/docs/5.8/queries#retrieving-results

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM