have an issue with eloquent. Have request
$item = Store::select('id','name')
->with(['product.cart' => function ($query) use($cartWhere) {
$query->where($cartWhere);
}])
->whereHas('product.cart', function ($query) use($cartWhere) {
$query->where($cartWhere);
})
->get();
and middle chain product from product.cart I receive this
select * from `products` where `products`.`store_id` in (2, 3, 4) and `products`.`deleted_at` is null
But why eloquent ignore my ->whereHas filter? Store filtered right, cart filter right, but product ignore it. how I can make that I receive an only product that needs me (exist in cart). Cart table has product_id foreign key
Can I make this via eloquent? or I need to use raw SQL and make this manually?
EDIT v1: Additional info
product table has column store_id
cart table has column product_id,quantity,site_id,user_id,id
$cartWhere variable
$cartWhere['site_id'] =$current_site_id;
$cartWhere['user_id'] = $user_id;
Related
I'm having some trouble calculating the price of my carts with eloquent,
here are my tables:
cart_products:
- cart_id
- product_id
- quantity
products:
- price
One cart can have multiple cart_products, and each cart_products have one product associated
I'm making the request from the Cart Model, I'm trying to get the total price of the cart (cart_products.quantity * products.price).
Here is my query:
Cart::select('cart.*', \DB::raw('IFNULL(SUM(products.price*cart_products.quantity), 0) AS cart_price'))
->leftJoin('cart_products', 'cart.id', '=', 'cart_products.cart_id')
->join('products', 'cart_products.product_id', '=', 'products.id');
When I'm doing that, I do get the expected result but all the carts that doesn't contains product are excluded, I would like them to be included.
How could I include them ? Or is there a better way to do it (I saw withCount method but I couldn't make it work properly) ?
Another way would be to setup a virtual relation in your cart model and calculate your cart price like
class Cart extends Model
{
public function price()
{
return $this->hasOne(CartProducts::class, 'cart_id')
->join('products as p', 'product_id', '=', 'p.id')
->groupBy('cart_id')
->selectRaw('cart_id,IFNULL(SUM(products.price*cart_products.quantity), 0) as cart_price');
}
}
To get price data for your carts your can query as
Cart::with('price')->get()->sortByDesc('price.cart_price');
I finally managed to do it another way using raw SQL:
Cart::select('cart.*', \DB::raw('(SELECT IFNULL(SUM(products.price*cart_products.quantity), 0) from cart_products join products on products.id = cart_products.product_id where cart_products.cart_id = cart.id) AS cart_price'));
Thanks to you all for your help !
I have an orders table, an items table, and a pivot table called item_order which has two custom fields (price, quantity). The relationship between Order and Item is belongsToMany. I'm trying to return the count of all items with an id of 1, where the parent Order->status == 'received'. For the life of me, I can't figure out how to do this.
class Order extends Model
{
public function items()
{
return $this->belongsToMany(Item::class)->withPivot('price', 'quantity');
}
}
class Item extends Model
{
public function orders()
{
return $this->belongsToMany(Order::class)->withPivot('price', 'quantity');
}
}
Try this:
$total_quantity = Item::find(1) // getting the Item
->orders() // entering the relationship
->with('items') // eager loading related data
->where('status', '=', 'received') // constraining the relationship
->get() // getting the results: Collection of Order
->sum('pivot.quantity'); // sum the pivot field to return a single value.
The strategy here is to find the desired Item to then get the related Orders to this Item that has a 'received' status, to finally sum the pivot attribute in order to get a single value.
It should work.
Considering you know the id of the item, most performant way would be to query item_order table directly. I would create a pivot model for ItemOrder and define the belongsTo(Order::class) relationship and do this:
$sum = ItemOrder::where('item_id', $someItemId)
->whereHas('order', function ($q) {
return $q->where('status', 'received');
})
->sum('quantity');
In Laravel, how can I reject a record in a query based on a value with one of the table with which this table has relations?
For example, I have the Products table and the Categories table. The Categories table has a one-to-many relationship, one category can have many products. The categories table are is_visible is_deleted. How to make inquiries on the Products table so that it rejects products that belong to the category that has and set fields is_visible = false or is_deleted = true ?
I tried something like this:
$products = ProductTable::join('product_category_tables', 'product_category_tables.id', '=', 'product_tables.id')
->where('product_category_tables.is_visible', '=', true)
->where('product_category_tables.is_deleted', '=', false)
->where('product_tables.is_visible', '=', true)
->where('product_tables.is_deleted', '=', false)
->paginate(50);
But from this query I have only one record. I can't make this query on Category table becouse I want get only 25/50/100 products for paginate.
If you are using Laravel Modal(Eloquent) and have defined the one to many relationship properly in both Product and Category Model. then you can achieve this by the following query:
$products = Product::where("is_visible", true)
->where("is_deleted", false)
->whereHas('category', function($categories){
$categories->where("is_visible", true)
->where("is_deleted", false);
})
->get();
In Product model you should have defined the relationship as bellow:
public function category()
{
//From your mentioned query I am seeing that
//product table's id is actually categories table's id(which should not be like this though),
//so the relationship is
return $this->belongsTo(Category::class, 'id');
}
I have a query working perfect but I need it in ORM Laravel.
I just need this query in eloquent Query builder.
SELECT * FROM product where vendor_id in (
SELECT vendor_id from vendor where is_block = 0
);
Scenario : There are two tables. One for Product and other for Vendor.
I want to select product from Product table. Each product belong to a vendor. If vendor is blocked then don't select product.
If is_block attribute is 0 then its mean that vendor is not block. If is_blocked=1 then vendor is blocked. I need to select only products of a vendor whose is_block = 0.
Use the whereHas() method:
Product::whereHas('vendor', function($q) {
$q->where('is_block', 0);
})->get();
Or the whereDoesntHave() method:
Product::whereDoesntHave('vendor', function($q) {
$q->where('is_block', 1);
})->get();
Make sure you've defined the relationship in the Product model:
public function vendor()
{
return $this->belongsTo(Vendor::class);
}
I am trying to get a single column of an inner joined model.
$items = Item::with('brand')->get();
This gives me the whole brand object as well, but I only want brand.brand_name
$items = Item::with('brand.brand_name')->get();
DidnĀ“t work for me.
How can I achieve this?
This will get related models (another query) with just the column you want (an id, see below):
$items = Item::with(['brand' => function ($q) {
$q->select('id','brand_name'); // id is required always to match relations
// it it was hasMany/hasOne also parent_id would be required
}])->get();
// return collection of Item models and related Brand models.
// You can call $item->brand->brand_name on each model
On the other hand you can simply join what you need:
$items = Item::join('brands', 'brands.id', '=', 'items.brand_id')
->get(['items.*','brands.brand_name']);
// returns collection of Item models, each having $item->brand_name property added.
I'm guessing Item belongsTo Brand, table names are items and brands. If not, edit those values accordingly.
Try this:
$items = Item::with(array('brand'=>function($query){
$query->select('name');
}))->get();