Admin: order history

  • On this page, the administrators get an overview of all orders that have already been placed

Preparation

Create controller

  • Create a new OrderController in the folder app/Http/Controllers/Admin
    • Run the command php artisan make:controller Admin/OrderController
  • Add an index() method to show the complete order history


 
 
 
 
 
 
 
 


class OrderController extends Controller
{
    // Show the complete order history
    public function index ()
    {
        $orders = [];
        $result = compact('orders');
        Json::dump($result);
        return view('admin.orders.index', $result);
    }
}
1
2
3
4
5
6
7
8
9
10
11

Basic view

  • Make a basic view index.blade.php inside the folder resources/views/admin/orders
  • Open the file resources/views/admin/orders/index.blade.php and update the view
@extends('layouts.template')

@section('title', 'Overview orders')

@section('main')
    <h1>Overview orders</h1>
@endsection
1
2
3
4
5
6
7

Add a route

  • Open routes/web.php and add a new GET route for showing the order history


 


Route::middleware(['auth', 'admin'])->prefix('admin')->group(function () {
    ...
    Route::get('orders', 'Admin\OrderController@index');
});
1
2
3
4

Overview orders

  • The overview is just a static view with a Bootstrap card (containing a table) for every order made so far

REMARK

  • To make it easier to understand what's happening behind the scenes, you first have to make a couple of orders with different users
  • It's important that the last order (in this example the order with id = 4):
    • comes from the user ITF User 5 (email: itf_user_5@mailinator.com and password: itfuser5)
    • contains the records 1 x The Clash - London Calling and 2 x Sonic Youth - EVOL
  • The final result is:

Final result

  • Notice that every card (every order) contains data from three different tables:
    • table orderlines (red)
    • table orders (green)
    • table users (yellow)

Database model

Update the controller

  • When we look at the result, every Bootstrap card represents one order
    • The orders table is the starting point for our selection


 
 





public function index ()
{
    $orders = Order::orderByDesc('id')
        ->get();
    $result = compact('orders');
    Json::dump($result);
    return view('admin.orders.index', $result);
}
1
2
3
4
5
6
7
8
  • Now we have our green items for the view

Orders

  • Next, we have to incorporate the parent table (orderlines) and the child table (users)
    • This can be done using the with() method


 
 






public function index ()
{
    $orders = Order::with(['orderlines', 'user'])
        ->orderByDesc('id')
        ->get();
    $result = compact('orders');
    Json::dump($result);
    return view('admin.orders.index', $result);
}
1
2
3
4
5
6
7
8
9

REMARK

  • The names used inside the (array) parameter of the with() method refer to the names of the relation methods we defined in the Order model (app/Order.php)!
    • orderlines(){} implements a one-to-many relation (hasMany()) with the orderlines table
    • user(){} implements a many-to-one relation (belongsTo()) with the users table
  • At this point we have all the (green, red and orange) information we need for our view

Orders with orderlines and user

  • If you want to exclude columns from the starting table you can use the select() method
  • If you want to exclude some columns from a parent/child table you can do this inside the with() method
    • Type a colon after the relation name and specify which columns of the relationship (separated by a comma) you would like to retrieve

REMARK

When using this feature, you should ALWAYS include the id column and any relevant foreign key columns in the list of columns you wish to retrieve



 
 







public function index ()
{
    $orders = Order::with(['orderlines:id,order_id,artist,title,cover,total_price,quantity', 'user:id,name,email'])
        ->select(['id','user_id','total_price','created_at'])
        ->orderByDesc('id')
        ->get();
    $result = compact('orders');
    Json::dump($result);
    return view('admin.orders.index', $result);
}
1
2
3
4
5
6
7
8
9
10

Orders with filter

Update the view

  • Loop over all orders and place each order in a Bootstrap card
  • Place a Bootstrap table inside the body of the card
    • Loop over all orderlines and generate separate rows inside the table
  • Pay special attention to the date inside the card header!
    • When adding the date using $order->created_at, you get the full date with the timestamp 2020-04-08 09:15:18, as this is the format in our database
    • You can format a date field inside Blade with format()
      • The format string argument within this method corresponds to the default PHP date formats, e.g:
        $order->created_at->format('M d Y') returns Apr 08 2020
        $order->created_at->format('l: n-j-Y') returns Wednesday: 4-8-2020


 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


@section('main')
    <h1>Overview orders</h1>
    @foreach($orders as $order)
        <div class="card mb-3 shadow">
            <div class="card-header">
                <p class="float-right"><i class="fas fa-shopping-cart"></i> {{$order->id}}</p>
                <p><i class="fas fa-user"></i> <a href="$order->user->email">{{$order->user->name}}</a>
                    <span class="text-muted ml-5"><i class="fas fa-clock"></i> {{$order->created_at->format('M d Y')}}</span>
                </p>
            </div>
           <div class="card-body">
                <table class="table">
                    <thead>
                    <tr>
                        <th class="width-50">Qty</th>
                        <th class="width-100">Price</th>
                        <th class="width-100"></th>
                        <th>Record</th>
                    </tr>
                    </thead>
                    <tbody>
                    @foreach($order->orderlines as $orderline)
                        <tr>
                            <td>{{$orderline->quantity}}</td>
                            <td>{{$orderline->total_price}}</td>
                            <td><img class="img img-thumbnail" src="{{$orderline->cover}}" alt="{{$orderline->title}}">
                            </td>
                            <td>{{$orderline->artist}} - {{$orderline->title}}</td>
                        </tr>
                    @endforeach
                    </tbody>
                </table>
            </div>
            <div class="card-footer">
                Total price: <b>{{$order->total_price}}</b>
            </div>
        </div>
    @endforeach
@endsection
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

Final result

Last Updated: 6/9/2020, 2:12:33 PM