How to join relationships in Eloquent? - php

I'm stuck in a problem, I have these 3 models: Order, OrderItem and Product, each Order has many Order Items, and each Order Item has one Prduct but a Product can be ordered several times.
Product has a supplier ID column (each supplier has many Products).
So here are the relationships:
Model: Order:
public function items(){
return $this->hasMany('App\Models\OrderItem','id','order_id');
}
Model OrderItem
public function order(){
return $this->belongsTo('App\Models\Order','order_id','id');
}
public function product(){
return $this->belongsTo('App\Models\Product','item_id','id');
}
Model Product
public function orders()
{
return $this->hasMany('App\Models\OrderItem','item_id','id');
}
What I want is that given a supplier_id, I need to filter Products for that supplier_id, and get the Order Items for that supplier_id and then group them by created date which is only available in the Order Model and not Order Items.
In other words, I want to get all Orders of a given supplier (through the supplier_id column in products) grouped by their creation date but there is no direct relation from Orders to Products I have to get Order Items to get to Products (Orders > Order Items > Products).
I thought about doing the following:
Product::with("orders")->where("supplier_id","=",$supplier_id)->join("orders","orders.id","=","products.orders")
The problem is that products.orders is a relationship (between Product and Order Item) and not a column.

You can do it using DB interface or if you'd like continue using Models you need to use multiple pluck.
You can do something like this:
Product::with(['orders','orders.order'])->where('supplier_id', $supplier_id)->get()->pluck("orders")->flatten()->pluck('order');

Use following snippet:
Product::select(DB::Raw('DATE(created_at) as cr'), ...)->where('supplier_id', $supplier_id)->with('orders.order')->groupBy('supplier_id')->get();
After that, you can loop on the result and group them by date:
$result->groupBy('cr')

Related

How to merge and sum up certain values of items that have the same ID value

So i have 2 tables. Orders and OrderItems. Relationship is each Order can have many OrderItems (orderitem is just a product).
OrderItem Table
id INT PRIMARY KEY
name TEXT
quantity INT
pack_value INT
order_id INT FOREIGN KEY REFERENCES ORDER_ID ON ORDERS TABLE
product_id INT FOREIGN KEY REFERENCES PRODUCT_ID ON PRODUCTS TABLE
Orders Table
order_id INT PRIMARY KEY
status TEXT
user_id INT FOREIGN KEY REFERENCES USER_ID ON USERS TABLE
An order can have the same OrderItem twice or only once. For example like below, 3 items but 2 products:
OrderItem(id=1, product_id=100, name="Pizza", quantity=2, pack_value=10, order_id=7)
OrderItem(id=2, product_id=100, name="Pizza", quantity=10, pack_value=1, order_id=7)
OrderItem(id=3, product_id=555, name="Olives", quantity=5, pack_value=1, order_id=7)
So above there is 2 entries for Pizza and this is the result i get. However i want it to only show 1 entry for Pizza because its the same item. Below is what i want to see:
OrderItem(product_id=100, name="Pizza", quantity=30, pack_value=1, order_id=7)
OrderItem(product_id=555, name="Olives", quantity=5, pack_value=1, order_id=7)
So essentially, if the item only exists once, then do nothing to it. If it exists twice, then make the pack_value=1 and the quantity is the sum of the individual quantity*pack_value. So in example above quantity becomes (2*10 + 10*1 = 30).
The controller method is like below, and so here is where I want to do this:
public function showOrderDetails(Order $order){
return view('orders.show', compact('order'));
}
Also the Order and OrderItem models has the method for the relationships. For example, in the Order Model i have:
public function orderItems(){
return $this->hasMany(OrderItem::class, 'order_id');
}
Thanks, and if you need any extra info i can provide.
SELECT name,
SUM(quantity * pack_value) AS quantity,
1 AS pack_value,
order_id
FROM order_items
GROUP BY name,
order_id;
fiddle
Merge another tables to this code using it as subquery, or add them into FROM clause (adjusting its output list and grouping expression) if needed.

Laravel Cart Sum based on input from 2 different tables

I have 2 tables Bag(cart) and products. I am saving quantity added by user in bad table and sale_price in products table. I need to get sum of bag.quantity * products.sale_price for each item. I am using query builder to get sum. How can i get that
I am able to use join to get list of all attributes
$items = DB::table('bag')->where('bag.user_id' , $user_id)->where('bag.order_id', 0)->join('products','products.id','=','bag.product_id')->get();
api link:
https://apptest.factory2homes.com/api/get-bag-products/3
I need to multiply quantity and sale_price for each unique product_id and then take total sum of it
you can use selectRaw to do such thing:
$items = DB::table('bag')->where('bag.user_id' , $user_id)
->where('bag.order_id', 0)
->join('products','products.id','=','bag.product_id')
->selectRaw('*, (bag.quantity * products.sale_price) as totalPrice')
->get();
and to get sum of all, you can use sum:
$sum=$items->sum('totalPrice');

Laravel eloquent get items belonging to a certain category

I have the following table structure
tables
tbl_items
id
sub_category_id //foreign key
table subcategories
tbl_subcategories
id
category_id
name
table categories
tbl_categories
id
name
As you can see from the above the sub_category_id is a foreign key in products table which relates to the id in the subcategories table. the subcategories table have a category_id which is a foreign key from the categories table
Now i wanted to fetch all items belonging to a certain category.
so i have tried
$categories = Categories::where('id',7)->first();
//from categories get subcategoryid
$allsubcategories = Subcategories::where('category_id',$categories->id)->pluck('id')
$allitems = Items::where('status',1)->wherein('sub_category_id',$allsubcategories)
The above works. but is there a neater way to do this?
define a hasManyThrough relationship in the Category model to the Item model.
// on the Category Model
public function items() {
return $this->hasManyThrough(Items::class, Subcategories::class);
}
then you can access all the items belongs to a particular category
// On your Controller
$category = Categories::where('id',7)->first();
$items = $category->items
official documentation - https://laravel.com/docs/5.7/eloquent-relationships#has-many-through
Well you could probably try using Nested Eager Loading, which should be a little more efficent:
//Assuming the relationships are named subCategories() on Categories model & items() on Subcategories model
$cat = Categories::where('id', 7)
->with('subCategories.items')
->get()
->first();
That should load the category w/ all the subCategories and all the items within each subCategories with the least amount of queries.

How get needed rows from 3 table in Laravel 5.5

I have 3 tables, Order, Products, Order_Products. I need get all field from order and products, thats ok using hasManyThrough(). But i need 1 more field from Order_products. How can i get this field ?
public function products()
{
//in order model
return $this->hasManyThrough('App\Models\Product','App\Models\OrderProduct','order_id','id','id','product_id');
}
using sql i need query like
SELECT
products.*, order_products.order_id, order_products.count as order_count
FROM
products
INNER JOIN order_products ON order_products.product_id = products.id
WHERE
order_products.order_id = 2
You can access intermediate table fields by using pivot attribute on model.
Lets say you have product, Then you can access count field of orders_products
$product->pivot->count;

QueryBuilder: Sum values of a pivot table

I'm new on Laravel & Eloquent. I have Users, Products and Votes tables on my DB. Users can vote (0 to 5) on products, so it is a "many to many" relationship, with the Votes table acting like a pivot:
Users: id, name, email, password
Products: id, name, model, brand
Votes: user_id, product_id, vote
I mapped this schema like this:
// User model:
public function product_votes()
{
return $this->belongsToMany('App\Product', 'votes')->withPivot('vote');
}
// Product model:
public function product_votes()
{
return $this->belongsToMany('App\User', 'votes')->withPivot('vote');
}
So John can vote 5 on product X and 0 on product Y. Bob can vote 2 on product X, 3 on product Y, and so on...
I'm trying to query all products, with the sum of votes of each one of them. Something like:
SELECT p.*, (SUM(v.vote) / COUNT(*)) as votes FROM products p INNER JOIN votes v on v.product_id = p.id GROUP BY p.id
How can I do that with QueryBuilder? My mapping is right?
The following will do the trick:
Product::select('products.*', DB::raw('SUM(vote)/COUNT(*) as votes'))
->join('votes', 'votes.product_id', '=', 'products.id')
->groupBy('products.id')
->get();
You can see the query that will be run by calling toSql() instead of get().

Categories