Trying to get only the specific products for each order in Laravel using arrays

Viewed 835

I am trying to display an order page for users based on two tables: orders and order_product.

The orders table keeps all the useful data for an order, as seen in the model:

Order.php

    protected $fillable = [
        'user_id', 'billing_fname', 'billing_lname', 'billing_email', 'billing_phone','billing_address',
        'billing_county', 'billing_locality', 'billing_zipcode', 'billing_total', 'shipped'
    ];
public function user(){
        return $this->belongsTo('App\User');
    }

    public function products(){
        return $this->belongsToMany('App\Product')->withPivot('quantity');
    }

The order_product table displays infos about how many products were bought on that order and what quantity for each product.

OrderProduct.php

protected $table = 'order_product';

    protected $fillable = ['order_id', 'product_id', 'quantity'];

Now, the problem is I want to display all these bounded infos in a view but I am getting all the products id's from all the orders not only the specific one:

myorders.blade.php

<ul class="order-list">
    @foreach($orders as $order)
    <div class="list-group">
  <a href="#" class="list-group-item list-group-item-action flex-column align-items-start active">
    <div class="d-flex w-100 justify-content-between">
      <h5 class="mb-1">Order {{$order->id}}</h5>
      <small>
        @if(!$o->shipped)
            Not shipped.
        @else
            Shipped.
        @endif
    </small>
    </div>
    <p class="mb-1">User: {{$order->billing_fname}} {{$order->billing_lname}} | Date: {{$order->created_at}} | Total: {{$order->billing_total}} $</p>
    <small>Adresa: {{$order->billing_county}} {{$order->billing_address}} {{$order->billing_city}}</small>
  </a>
  @foreach($products as $product)
  <a href="#" class="list-group-item list-group-item-action flex-column align-items-start">
    <div class="d-flex w-100 justify-content-between">
      <h5 class="mb-1">{{$product->name}}</h5>
      <small class="text-muted">Cantitate: {{$product->quantity}}</small>
    </div>
    <p class="mb-1">Price: {{$product->price}}</p>
  </a>
  @endforeach
</div>
@endforeach
    </ul>

In the controller I tried to access all the data in 3 different foreach statements, as follows:

OrderController

public function index()  
    {  
            
        $user_id = Auth::user()->id;
        $orders = Order::where('user_id', $user_id)->get();   //from orders table I need all the orders placed by the authenticate user 

        $items = array();
        foreach($orders as $order){
            $items[] = OrderProduct::where('order_id', $order->id)->first();     //from order_product (the pivot table) I need all the data from order_id equals the id in orders
        }

        $products = array();
        foreach($items as $item){
            $prod = Product::where('id', $item->product_id)->first();   //searching for the products in the products table with the id's from order_product
            $products[] = $prod;
        }
        return view('orders.myorders', array(
            'orders' => $orders,
            'products' => $products
        ));

        // dd($products);
        
    } 

What I am getting is all the products foreach order, so the view looks something like:

First order id:

-all the products found in array

Second order id:

-again all the products found in array

-and so on, while I only need the specific products for that order

Please feel free to ask anything if I wasn't clear enough. I am new in this field and I would appreciate any piece of advice.

Thanks a bunch.

2 Answers

I solved this by using the following logic:

//details of a specific order
    public function index($id) {
        $orders = Order::where('_id', $id)->first();
        
        $details = OrderProduct::where('order_id', $id)->get();    //for an order with the same id we can have multiple products => array
        $product_id = OrderProduct::where('order_id', $id)->get(['product_id']);    //accessing the product from the linked table

        $items = array();
        $products = array();
        foreach($details as $detail){
            $items[] = $detail->product_id;    //an array with all the details from the specific order

            $prod = Product::findOrFail($detail->product_id);   //we add the products with the corresponding id in our products array
            $products[] = $prod;
        }

        return view('orders.myorder', array(
            'orders' => $orders,
            'details' => $details,
            'products' => $products   //returning all the details, orders for accessing the details from Orders, details for accessing all the product's id from that order (OrderProduct and products for getting access to all the products (Products)
        ));

        // dd($items);
    }

And the blade file which displays all the details:

<div class="container">
    <h3 class="text-center">{{ __('Order no.') }} {{$orders['id']}}</h3>
<div class="container-fluid">
  <div class="row">
    <div class="col-sm-4">
    <h5 class="my-5">{{ __('User Details') }}</h5>
         <div class="form-group">
            <p><strong>{{ __('First Name') }}: </strong><em><strong>{{$orders['billing_fname']}} {{$orders['billing_lname']}}</strong></em></p>
         </div>
         <div class="form-group">
            <p><strong>{{ __('Last Name') }}: </strong><em><strong>{{$orders['billing_email']}}</strong></em></p>
         </div>
         <div class="form-group">
            <p><strong>{{ __('Phone') }}: </strong><em><strong> {{$orders['billing_phone']}}</strong></em></p>
         </div>
         <div class="form-group">
            <p><strong>{{ __('Address') }}: </strong><em><strong> {{$orders['billing_address']}}</strong></em></p>
         </div>
         <div class="form-group">
            <p><strong>{{ __('County') }}: </strong><em><strong> {{$orders['billing_county']}}</strong></em></p>
         </div>
         <div class="form-group">
            <p><strong>{{ __('City') }}: </strong><em><strong> {{$orders['billing_city']}}</strong></em></p>
         </div>
         <div class="form-group">
            <p><strong>{{ __('Zipcode') }}: </strong><em><strong> {{$orders['billing_zipcode']}}</strong></em></p>
         </div>
         <div class="form-group">
            
            <p><strong>{{ __('Total') }}: </strong><em><strong> {{$orders['billing_total']}}</strong></em></p>
         </div>
         <div class="form-group">
            <p><strong>Status: </strong><em><strong> {{ $orders['shipped'] === "1" ? __('Shipped') : __('Not shipped') }}</strong></em></p>
         </div>
    </div>
    <div class="col-sm-8">
    <h5 class="text-center mt-5">{{ __('Ordered products') }}</h5>
         <table class="table mt-3">
            <thead>
               <tr>
                  <th>{{ __('Product Name') }}</th>
                  <th>{{ __('Image') }}</th>
                  <th>{{ __('Price') }}</th>
                  <th>{{ __('Quantity') }}</th>
                  <th>{{ __('Date') }}</th>
               </tr>
            </thead>
            <tbody>
               @foreach($products as $product)
               <tr>
                  <td>
                     <a href="{{url(app()->getLocale().'/details', $product->slug)}}" style="text-decoration:none;"><p>{{ $product->name }}</p></a>
                  </td>
                  <td><a href="{{url(app()->getLocale().'/details', $product->slug)}}"><img src="../../img/{{$product['image']}}" width="100" height="100"></a></td>
                  <td>
                     <p>{{$product->price}} RON</p>
                  </td>
                    @foreach($details as $detail)
                        @if($product->id == $detail->product_id) 
                            <td><p>{{ $detail->quantity }} buc</p></td>
                        @endif
                   @endforeach 
                  <td>
                     <p>{{$orders['created_at']}}</p>
                  </td>
               </tr>
               @endforeach
            </tbody>
         </table>
         <div class="float-right m-4">
            <a class="btn btn-info m-4" href="{{ url(app()->getLocale().'/myorders') }}">{{ __('Back') }}</a>
        </div>
    </div>
  </div>
</div>
</div>

This might be a little bit too difficult to follow, my logic is quite complicated but I hope some of you may find some help in it.

You can do this with less coding, with these changes:

changes in Order.php

 public function orderProducts(){
    return $this->hasMany('App\OrderProduct');
}

changes in OrderProduct.php

 public function products(){
    return $this->hasOne('App\Product')->withPivot('quantity');
}

changes in OrderController.php:

 public function index()  
{  
   
    $user_id = Auth::user()->id;
    $orders = Order::where('user_id', $user_id)->get();   
    return view('orders.myorders', array('orders' => $orders));
}

and changes in myorders.blade.php:

<ul class="order-list">
@foreach($orders as $order)
<div class="list-group">
  <a href="#" class="list-group-item list-group-item-action flex-column align-items-start active">
    <div class="d-flex w-100 justify-content-between">
      <h5 class="mb-1">Order {{$order->id}}</h5>
      <small>
        @if(!$o->shipped)
            Not shipped.
        @else
            Shipped.
        @endif
    </small>
    </div>
    <p class="mb-1">User: {{$order->billing_fname}} {{$order->billing_lname}} | Date:     {{$order->created_at}} | Total: {{$order->billing_total}} $</p>
    <small>Adresa: {{$order->billing_county}} {{$order->billing_address}} {{$order->billing_city}}</small>
  </a>
  @foreach($order->orderProducts()->get() as $orderProduct)
  <a href="#" class="list-group-item list-group-item-action flex-column align-items-start">
    <div class="d-flex w-100 justify-content-between">
      <h5 class="mb-1">{{$orderProduct->product->name}}</h5>
      <small class="text-muted">Cantitate: {{$orderProduct->product->quantity}}</small>
    </div>
    <p class="mb-1">Price: {{$orderProduct->product->price}}</p>
  </a>
  @endforeach
</div>
@endforeach
</ul>
Related