I have a sql query, and i want to know if it can be written in eloquent.
There are two tables Brands and Products.
I am trying to get the brands which are in particular category of products
Below is how it looks currently
\DB::select('select * FROM brands WHERE id in ( select brand_id from products WHERE category_id IN (220, 222, 223) GROUP by brand_id )');
The above is working, i want help on converting it to eloquent.
Assuming you've already prepped Brand and Product models, you can specify closure to include subquery inside your WHERE IN clause like this:
Brand::whereIn('id', function ($query) {
$query
->select('brand_id')
->from('products')
->whereIn('category_id', [220, 222, 223])
->groupBy('brand_id');
})->get();
You want to have your models set up so you can query them using Eloquent; when you have those you can do:
$categoryIds = [220, 222, 223];
$brandIds = Product::whereIn('category_id', $categoryIds)
->groupBy('brand_id')
->pluck('brand_id');
$yourQuery = Brand::whereIn('id', $brandIds)->get();
Considering that you have your model Brand and Products to do it you will do:
$brands = Brand::with(['category'=>function($query){ $query->select('category_id')}])->whereIn('category_id',[220, 222, 223])->get();
Related
I have a Relation of products with categories using category_products as a pivot table. I want to get/take 5 products from each category but it not working correctly.
I have tried all the methods known to me I could find the solution
$query = $this->getQuery();
$query->where('parent_id','0')->with('categoryProducts',function($q1){
$q1->with('product',function ($q){
$q->orderBy('sold', 'desc');
})->take(4);
})->whereHas('categoryProducts');
return $query->get();
I have two models Products and ProductImage.
I've created a one to many relationship in the Product model as follows:
public function images()
{
return $this->hasMany(ProductImage::class);
}
From my controller, I'm trying to retrieve all 'shown' products and their related images in the product_images table as follows:
$products = Product::find(1)->images()
->where('shown', 1)
->get();
There is a shown column in my products table but not in the product_images table so I'm getting this error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'shown' in
'where clause' (SQL: select * from `product_images` where
`product_images`.`product_id` = 1 and `product_images`.`product_id` is not
null and `shown` = 1)
Why is the query trying to apply the where condition to the product_images table as opposed to the products table?
How can can I achieve the desired result of getting all products and their related images?
you can do something like this
$products = Product::where('shown',1)->with('images')
->get();
This query will get the shown products and eager load the related images for each product
$products = Product::where('shown',1)->with('product_images')
->get(); and column product_id mustbe in product_images table
I have these tables:
products: id, name
orders: id, number
order_items: order_id, product_id
So I want to get best order products. And i make this code below.
$sales = DB::table('products')
->leftJoin('order_items','products.id','=','order_items.product_id')
->leftJoin('orders','orders.id','=','order_items.order_id')
->selectRaw('products.*, COALESCE(sum(orders.item_count),0) total')
->groupBy('products.id')
->orderBy('total','desc')
->take(6)
->get();
Please help me convert query above to eloquent. This work but I want to get products morphed images too.
Eloquent also support leftJoin, so you can do something like this:
$sales = Product::query()
->leftJoin('order_items','products.id','=','order_items.product_id')
->leftJoin('orders','orders.id','=','order_items.order_id')
->selectRaw('products.*, COALESCE(sum(orders.item_count),0) total')
->groupBy('products.id')
->orderBy('total','desc')
->take(6)
->get();
But if you mean you want to use eager load, please share your models and these relations first,
Assuming you created proper relationships in the Product model, would look something like this:
Product::with('order_items', 'orders')
->selectRaw('COALESCE(sum(orders.item_count),0) as total')
->orderByDesc('total')
->limit(6)
->get();
Say I have 2 models, Category and POI where 1 Category can have many POIs.
$categoryDetails = Category::with([
'pois' => function ($query) {
$query->where('is_poi_enabled', true);
},
])->findOrFail($id);
The above query returns results from the specific Category as well as its POIs.
However, with the query below:
$query->select('id', 'name')->where('is_poi_enabled', true);
The POIs become empty in the collection.
Any idea why this is happening? When added a select clause to the Eloquent ORM?
While doing a select it's required to fetch the Relationship local or Primary key.
For an example POIs table contains category_id then it's required to select it
Try this:
$categoryDetails = Category::with([
'pois' => function ($query) {
$query->select(['id', 'category_id', 'is_poi_enabled'])
->where('is_poi_enabled', true);
},
])->findOrFail($id);
Good luck!
I've found the concept and meaning behind these methods to be a little confusing, is it possible for somebody to explain to me what the difference between has and with is, in the context of an example (if possible)?
With
with() is for eager loading. That basically means, along the main model, Laravel will preload the relationship(s) you specify. This is especially helpful if you have a collection of models and you want to load a relation for all of them. Because with eager loading you run only one additional DB query instead of one for every model in the collection.
Example:
User > hasMany > Post
$users = User::with('posts')->get();
foreach($users as $user){
$users->posts; // posts is already loaded and no additional DB query is run
}
Has
has() is to filter the selecting model based on a relationship. So it acts very similarly to a normal WHERE condition. If you just use has('relation') that means you only want to get the models that have at least one related model in this relation.
Example:
User > hasMany > Post
$users = User::has('posts')->get();
// only users that have at least one post are contained in the collection
WhereHas
whereHas() works basically the same as has() but allows you to specify additional filters for the related model to check.
Example:
User > hasMany > Post
$users = User::whereHas('posts', function($q){
$q->where('created_at', '>=', '2015-01-01 00:00:00');
})->get();
// only users that have posts from 2015 on forward are returned
The documentation has already explained the usage, so I will use SQL to explain the methods.
Example:
Assuming there is an Order (orders) has many OrderItem (order_items) and you already built the relationship between them:
// App\Models\Order:
public function orderItems() {
return $this->hasMany('App\Models\OrderItem', 'order_id', 'id');
}
These three methods are all based on a relationship.
with
Result: with() return the model object and its related results.
Advantage: It is eager-loading which can prevent the N+1 problem.
When you are using the following Eloquent Builder:
Order::with('orderItems')->get();
Laravel change this code to only two SQL:
// get all orders:
SELECT * FROM orders;
// get the order_items based on the orders' id above
SELECT * FROM order_items WHERE order_items.order_id IN (1,2,3,4...);
And then Laravel merges the results of the second SQL query with the results of the first SQL by foreign key, finally returning the collection results.
So if you selected columns without the foreign_key in a closure, the relationship result will be empty:
Order::with(['orderItems' => function($query) {
// $query->sum('quantity');
$query->select('quantity'); // without `order_id`
}
])->get();
#=> result:
[{ id: 1,
code: '00001',
orderItems: [], // <== is empty
},{
id: 2,
code: '00002',
orderItems: [], // <== is empty
}...
}]
has
Has will return the model's object when its relationship is not empty.
Order::has('orderItems')->get();
Laravel changes this code to one SQL query:
select * from `orders` where exists (
select * from `order_items` where `orders`.`id` = `order_items`.`order_id`
)
whereHas
The methods whereHas and orWhereHas put where conditions on your has queries. These methods allow you to add customized constraints to a relationship constraint.
Order::whereHas('orderItems', function($query) {
$query->where('status', 1);
})->get();
Laravel changes this code to one SQL query:
select * from `orders` where exists (
select *
from `order_items`
where `orders`.`id` = `order_items`.`order_id` and `status` = 1
)