I have three tables - users, products and orders
There is a relation between users and orders (users has many orders).
orders table contains product_id and user_id column.
Now I want to access the product details of orders for a user.
What I am trying:
public function myOrders(){
$orders = Auth::user()->orders->pluck('product_id');
$products = Product::find($orders);
return view('shop.myorders', compact('products'));
}
But this is not working. Can anyone help me? What other way can be better to achieve this?
As mentioned, find() will always return 1 item, and expects a string/int for the parameter. You want to use where and get instead. With an array of ids, you can use whereIn.
public function myOrders(){
$orders = Auth::user()->orders->pluck('product_id');
$products = Product::whereIn('id', $orders)->get();
return view('shop.myorders', compact('products'));
}
I assume you have orders() relation defined in the Product model:
public function orders()
{
return $this->hasMany(Order::class)
}
Then you'll be able to load products from all user's orders:
$products = Product::whereHas('orders', function($q) {
$q->where('user_id', auth()->id())
})->get();
Related
I've spent two days trying to solve this but I can't figure how.
I have five tables
Product
Category
Category_Product
Order
Order_Product
From the view,clicking on a category button I have to fetch all his ordered products with the relative category.
I have the current models:
Product Model
class Product extends Model
{
public function categories() {
return $this->belongsToMany('App\Category');
}
public function orders() {
return $this->belongsTo('App\Order');
}
}
Category Model
public function products() {
return $this->belongsToMany('App\Product');
}
Order Model
public function products() {
return $this->belongsToMany('App\Product');
}
Now the problem is that I can't figure how to fetch the data from the current tables.When I press a button I'm able to fetch the category from the Product Table,but I want to fetch from the Ordered_Products. I really can't figure how.
With this I'm able to fetch all the categories from Product
if (request()->category) {
$products = Product::with('categories')->whereHas('categories', function ($query) {
$query->where('slug', request()->category);
})->get();
}
With this instead,I'm able to fetch the ordered products.
$products = DB::table('order_product')
->join('products', 'order_product.product_id','=', 'products.id')
->where('order_product.user_id','=',$user_id)
->get();
For the latter, there's a better way to do it, that's for sure. I'm sorry if it's a dumb question but I'm rather new with this framework. I am using Laravel 7.2.
Basically Eloquent Model doesn't encourage joining tables to retrieve data. It should be joined only for filtering results (So you need to drop field of other table using ->select('original_table.*'))
In this case, you should simply retrieve categories at first. Then retrieve related data using relation property accessing.
e.g.
$categories = Category::query()
->with('products')
->where('slug', request('category'))
->get();
$products = $categories->flatMap->products;
$pivots = $products->map->pivot;
Solved using whereHas two times:
$products = Product::with('categories')->whereHas('categories',function($query){
$query->where('slug',request()->category);
})->whereHas('orders',function($query){
$query->where('orders.user_id',Auth::id());
})->get();
Suppose I have Three model named as Customer ,Invoice and Payment.
Invoice and Payment model looks like
id , customer_id, amount
I want to get only those customer whose
Invoice.sum(amount)>Payment.sum(amount) with these amount difference
I am currently retrieve like
$customers=Customer::get();
foreach($customers as $customer)
{
$pay=Payment::where('customer_id',$customer->id)->sum('amount');
$due=Invoice::where('customer_id',$customer->id)->sum('amount');
if($due>$pay){
// showing this customers
}
}
Is there any better way with eloquent join?
How Can I get In laravel eloquent ?
Have you set any relationship in the Model? A better eloquent query will look like this. You might need to adjust a bit
Customer::join('payment','customer.id','=','payment.customer_id')
->join('invoice','customer.id','=','invoice.customer_id')
->select(array('customer.*'),DB::raw("SUM(payment.amount) as payment_sum,SUM(invoice.amount) as invoice_sum"))
//->where('customer_id',$customer->id)
->groupBy('customer.id') //replace with anything that make sense for you.
->havingRaw('invoice_sum > payment_sum')
->get();
Try this
First, define the relationship in your Customer Model
public function payments()
{
return $this->hasMany(Payment::class); //based on your logic or structure
}
public function invoices()
{
return $this->hasMany(Invoice::class); //based on your logic or structure
}
Customer::with(['payments' => function($query) {
$query->sum('amount');
}])
->get();
or
$customers=Customer::with('payments','invoices')->get();
foreach($customers as $customer)
{
$pay = $customer->payments()->sum('amount');
$due = $customer->invoices()->sum('amount');
//other logic
}
I've following data structure,
Product
id
name
description
Product Review
id
user_id
product_id
review
rating
status (true/false)
Relationship is one to many i.e. one product has many reviews.
What I want is to load all the products with verified reviews(i.e. reviews with status true)
I've tried following,
$products = Product::with('reviews')->get();
but when I iterate over $products to access reviews like $product->reviews, all the reviews(even status false reviews) are displayed.
Any kind of suggestion is appreciated.
You can add a closure to the with function to add extra filtering.
Product::with([
'reviews' => function ($query) { $query->where('status', true); }
])->get();
Another option is to add a filtered relation function to your product model.
public function verifyedReviews() {
return $this->reviews()->where('status', true);
}
And now call this function in your with clause.
Product::with('verifyedReviews')->get();
try this one by using clousre
$products = Product::with(['reviews' => fuction($query) {
return $query->where('status',true);
}])->get();
you can use WhereHas()
Your code would be:
$products = Product::whereHas('reviews',function($query){
return $query->where('status',true);
})->get();
I have two tables, say Products and Biddings where one product can be bid by many users. Naturally I have two models:
class Product extends Model
{
public function biddings()
{
return $this->hasMany('App\Bidding');
}
}
class Bidding extends Model
{
public function product()
{
return $this->belongsTo('App\Product');
}
}
So, say I want to get all products along with the highest priced bidding I did something like this.
$productBidding = DB::table('biddings')
->select('*', DB::raw('max(price) as price'))
->join('products', 'products.id', '=', 'biddings.product_id')
->groupBy('product_id')
->get();
That works well BUT I kinda want to do it Eloquent way. So how do I convert Query Builder way to Eloquent? I am currently on this but do not know how to put the "max" condition in.
$productBidding = Products::with('biddings')
->get();
$productbinding=Bidding:with('product')
->get();
foreach($productbinding as $productbind)
{
echo $productbind->product->name; // example
}
I would extract the highest bid to a separate function on the Product model, like so:
public function highestBid() {
return $this->biddings()->max('price');
}
Then fetch the products and get the highest bid:
$products = Product::get();
foreach ($products AS $product) {
echo $product->highestBid();
}
I have a many-to-many relation between Order and Item table.
This relationship is defined in Order model:
public function items()
{
return $this->belongsToMany('Item', 'order_item', 'order_id', 'item_id' );
}
If customer is adding an item to the order, he choose one item from a list
$items = Item::all();
and this chosen item is add in intermediate (pivot) table (order_id, item_id).
The problem is that, I need my items list to contains only these items which have NOT been chosen for this order before. i.e. pivot table does NOT contains these items combined to this specific order.
Pseudo code:
$all_Items = Item::all();
$previously_Selected_Items = select_From_Pivot_Table::where('order_id', '=', $id);
$required_Items_List = $all_items->exclude($previously_Selected_Items);
I'm using Laravel 4.2.
Any suggestions??
Thanks in advance.
You can use whereDoesntHave and filter the items using the relationship:
$items = Item::whereDoesntHave('orders', function($q) use ($id){
$q->where('order_id', $id);
})->get();
After some time of searching and trying some suggested ideas, I came up with easy, but not professional, solution:
$order = Order::where('id', '=', $id)->with('items')->first();
$allitems= Item::all();
then array_diff, a php function, did the trick:
$items = array_diff($allitems->lists('name','id'), $order->items->lists('name','id'));
but the $items is just a list of id and name, not the whole objects, which I need. So I need a better solution.