After many requests from from our users we have updated this tutorial to laravel 5.2 . we’ll be covering folowing laravel 5.2 features Authentication Scaffolding , Authentication Drivers / “Multi-Auth” , & Implicit model binding Too

Here is the link of Demo store created using this tutorial  by

Here is the github code of this store

In this tutorial , we’ll code a simple book store example using Laravel. We’ll also cover Laravel’s built-in authentication, named routes, and database seeding. We’ll also elaborate some rapid development methods that come with Laravel such as creating route URLs. Also, we’ll working with a new relation type called belongs to many. We’ll cover pivot tables as well. Our e-commerce application will be a simple book store. This application will have order, administration, and cart features. We will cover the following topics:

  • Building an authorization system
  • Creating and migrating authors, books, carts, and orders tables
  • Creating template files
  • Listing books
  • Building a shopping cart
  • Taking orders
  • Listing orders

 

Building an authorization system

We assume that you have already defined the database credentials in the database.php file located at config directory To create our e-commerce application, we need a database. You can create and simply run the following SQL command or basically you can use a database administration interface such as phpMyAdmin:

CREATE DATABASE laravel_store


Creating and migrating the members’ database

Contrary to most of the PHP frameworks, Laravel has a basic and customizable authentication mechanism. The authentication class is very helpful for rapidly developing applications. First, we need a secret key for our application. As we mentioned in previous chapters, the application’s secret key is very important for our application’s security because all the data is hashed salting this key. The artisan can generate this key for us with a single command line:

php artisan key:generate

If no error occurs, you will see a message that tells you the key is generated successfully. After key generation, if you’ve visited your project URL before you face problems with opening your Laravel application, simply clear your browser’s cache and try again. Next, we should edit the authentication class’s configuration file. To use Laravel’s built-in authentication class, we need to edit the configuration file, which is located at config/auth.php. This file contains several options for the authentication facilities. If you need a change in the table name, and so on, you can make the changes under this file. By default, Laravel comes with a User model. You can see the file, which is located at app/User.php. we also need to define which fields are fillable in ourUser model. Let’s edit User.php located at app and add the fillable array:

<?php

use IlluminateAuthUserInterface;
use IlluminateAuthRemindersRemindableInterface;

class User extends Eloquent implements UserInterface, RemindableInterface {

  protected $table = 'users';

  /**
   * The attributes excluded from the model's JSON form.
   *
   * @var array
   */  protected $hidden = array('password');

  //Add to the "fillable" array
   protected $fillable = array('email', 'password', 'name', 'admin');

  /**
   * Get the unique identifier for the user.
   *
   * @return mixed
   */  public function getAuthIdentifier()
  {
    return $this->getKey();
  }

  /**
   * Get the password for the user.
   *
   * @return string
   */  public function getAuthPassword()
  {
    return $this->password;
  }

  /**
   * Get the e-mail address where password reminders are sent.
   *
   * @return string
   */  public function getReminderEmail()
  {
    return $this->email;
  }

}

Basically we need four columns for our members. These are:

  • email: This is the column for storing a member’s e-mails
  • password: This is the column for storing a member’s password
  • name: This is the column for storing a member’s name and surname
  • admin: This is the column for flagging store admin

Now we need several migration files to create the users table and add a member to our database. To create a migration file, give a command as follows:

php artisan make:migration create_users_table --table=users --create

Open the migration file, which was created recently and located at database/migrations/. We need to edit the up() function, as shown in the following code snippet:

  public function up()
  {
    Schema::create('users', function(Blueprint $table)
    {
      $table->increments('id');
      $table->string('email');
      $table->string('password');
      $table->string('name');
      $table->integer('admin');
      $table->timestamps();
    });
  }

After editing the migration file, run the migrate command:

php artisan migrate

Now we need to create a database seeder file to add some users to the database. Database seeding is another highly recommended way to add data to your application database. The database seeder files are located at app/database/seeds. Let’s create our first seeder file under the UsersTableSeeder.php directory.

Note

We can create both the seeder file and the seeder class with any name. But it is highly recommended for the seeder file and class name that the table name should follow camel case, for example, TableSeeder. Following the world-wide programming standards will improve the quality of your code.

The content of UsersTableSeeder.php should look like the following:

<?php
Class UsersTableSeeder extends Seeder {
 
    public function run()
    {
  DB::table('users')->delete();
  
User::create(array(
            'email' => 'member@email.com',
            'password' => Hash::make('password'),
            'name' => 'John Doe',
            'admin'=>0
        ));
        
  User::create(array(
            'email' => 'admin@store.com',
            'password' => Hash::make('adminpassword'),
            'name' => 'Jeniffer Taylor',
            'admin'=>1
        ));  

    }
 
}

To apply seeding, first we need to call the Seeder class. Let’s open the DatabaseSeeder.php file located at app/database/seeds and edit the file, as shown in the following code snippet:

<?php
class DatabaseSeeder extends Seeder {

  /**
   * Run the database seeds.
   *
   * @return void
   */  public function run()
  {
    Eloquent::unguard();

    $this->call('UsersTableSeeder');
    $this->command->info('Users table seeded!');
  }

}

It is very important to securely store your users’ passwords and their critical data. Do not forget that if you change the application key, all the existing hashed records will be unusable because the Hashclass uses the application key as the salting key, when validating and storing given data.

or you can use fakers library to fill your database https://github.com/fzaninotto/Faker

 

Creating and migrating the authors’ database

 

We need an Author model for storing the book authors. It will be a very simple structure. Let’s create the Author.php file under app and add the following code:

<?php
Class Author extends Eloquent {

protected $table = 'authors';

protected $fillable = array('name','surname');

}

Now we need several migration files to create the authors table and add some authors to our database. To create a migration file, give a command as follows:

php artisan make:migration create_authors_table --table=authors --create

Open the migration file that was created recently and located at database/migrations/. We need to edit the up() function as follows:

  public function up()
  {
    Schema::create('authors', function(Blueprint $table)
    {
      $table->increments('id');
      $table->string('name');
      $table->string('surname');
      $table->timestamps();
    });
  }

After editing the migration file, run the migrate command:

php artisan migrate

As you know, the command creates the authors table and its columns. If no error occurs, check thelaravel_store database for the authors table and the columns.

Adding authors to the database

Now we need to create a database seeder file to add some authors to the database. Let’s create our first seeder file under database/seeds/AuthorsTableSeeder.php.

The content in AuthorsTableSeeder.php should look like the following:

<?php
Class AuthorsTableSeeder extends Seeder {
 
    public function run()
    {
DB::table('authors')->delete();

        Author::create(array(
            'name' => 'Lauren',
            'surname'=>'Oliver'
        ));

        Author::create(array(
            'name' => 'Stephenie',
            'surname'=>'Meyer'
        ));

        Author::create(array(
            'name' => 'Dan',
            'surname'=>'Brown'
        ));

    }
 
}

To apply seeding, first we need to call the Seeder class. Let’s open the file DatabaseSeeder.phplocated at database/seeds/and edit the file as shown in the following code snippet:

<?php
class DatabaseSeeder extends Seeder {

  /**
   * Run the database seeds.
   *
   * @return void
   */  public function run()
  {
    Eloquent::unguard();
    $this->call('UsersTableSeeder');
    $this->command->info('Users table seeded!');
    $this->call('AuthorsTableSeeder');
    $this->command->info('Authors table seeded!');
  }

}

We need to seed our database with the following artisan command:

php artisan db:seed

Note

When you want to rollback and re-run all migrations, you can use the following command:

php artisan migrate:refresh --seed

 

 

Creating and migrating the books database

We need a Book model to store the author’s books. Let’s create the Book.php file under app and add the following code:

<?php
Class Book extends Eloquent {

protected $table = 'books';

protected $fillable = array('title','isbn','cover','price','author_id');

public function Author(){

return $this->belongsTo('Author');

}

}

Let’s explain the role of the author_id column and the Author() function. As you know from previous chapters, Eloquent has several functions for different kinds of database relations. Theauthor_id will store the ID of the authors. The Author() function is used to fetch names and surnames of authors from the authors table.

Adding books to the database

Now we need to create a database seeder file to add some books to the database. Let’s create the first seeder file under app/database/seeds/BooksTableSeeder.php.

The content in BooksTableSeeder.php should look like the following:

<?php
Class BooksTableSeeder extends Seeder {

  public function run()
  {
  DB::table('books')->delete();

  Book::create(array(
    'title'=>'Requiem',
    'isbn'=>'9780062014535',
    'price'=>'13.40',
    'cover'=>'requiem.jpg',
    'author_id'=>1
   ));
  Book::create(array(
    'title'=>'Twilight',
    'isbn'=>'9780316015844',
    'price'=>'15.40',
    'cover'=>'twilight.jpg',
    'author_id'=>2
  ));
  Book::create(array(
    'title'=>'Deception Point',
    'isbn'=>'9780671027384',
    'price'=>'16.40',
    'cover'=>'deception.jpg',
    'author_id'=>3
  ));

  }
     
}

To apply seeding, first we need to call the seeder class. Let’s open the DatabaseSeeder.php file located at app/database/seeds and edit the file, as shown in the following code snippet:

<?php
class DatabaseSeeder extends Seeder {

  /**
   * Run the database seeds.
   *
   * @return void
   */  public function run()
  {
    Eloquent::unguard();
    $this->call('UsersTableSeeder');
    $this->command->info('Users table seeded!');
    $this->call('AuthorsTableSeeder');
    $this->command->info('Authors table seeded!');
    $this->call('BooksTableSeeder');
    $this->command->info('Books table seeded!');
  }

}

Now, we need to seed our database with the following artisan command:

php artisan db:seed

 

Creating and migrating the carts database

As you know, all e-commerce applications should have a cart. In this application, we’ll have a cart too. We’ll design a member-based cart, which means we can store and show each visitor their carts and cart items. So, we need a Cart model to store the cart items. It will be a very simple structure. Let’s create the Cart.php file under app/models and add following code:

<?php
Class Cart extends Eloquent {

protected $table = 'carts';

protected $fillable = array('member_id','book_id','amount','total');

public function Books(){

return $this->belongsTo('Book','book_id');

}

}

Now we need a migration file to create the carts table. To create a migration file, give a command such as the following:

php artisan make:mgration  create_carts_table --table=carts --create

Open the migration file, which was created recently and located at database/migrations/. We need to edit the up() function as shown in the following code snippet:

  public function up()
  {
    Schema::create('carts', function(Blueprint $table)
    {
      $table->increments('id');
      $table->integer('member_id');
      $table->integer('book_id');
      $table->integer('amount');
      $table->decimal('total', 10, 2);
      $table->timestamps();
    });
  }

To apply migration, we need to migrate with the following artisan command:

php artisan migrate

Creating and migrating the orders database

To store members’ orders, we need two tables. The first of them is the orders table, which will store shipping details, member ID, and the total value of the order. The second one is the order_bookstable. This table will store orders’ books and will be our pivot table. In this model, we’ll use thebelongsToMany() relation. This is because an order can have many books. So, first we need an Order model to store the book orders. Let’s create the Order.php file under app and add the following code:

<?php
Class Order extends Eloquent {

protected $table = 'orders';

protected $fillable = array('member_id','address','total');

public function orderItems()
    {
        return $this->belongsToMany('Book') ->withPivot('amount','total');
    }

}

As you can see in the code, we’ve used a new option named withPivot() with thebelongsToMany() function. With the withPivot() function, we can fetch extra fields from our pivot table. Normally, without the function, the relational query accesses from the pivot table with just the idobject of related rows. This is necessary for our application because of price changes. Thus, previous orders, which were possibly done before any price change, are not affected.

Now we need a migration file to create the carts table. To create a migration file, give a command such as the following:

php artisan make:migration  create_orders_table --table=orders --create

Open the migration file, which was created recently and located at database/migrations. We need to edit the up() function as follows:

  public function up()
  {
    Schema::create('orders', function(Blueprint $table)
    {
      $table->increments('id');
      $table->integer('member_id');
      $table->text('address');
      $table->decimal('total', 10, 2);
      $table->timestamps();
    });
  }

To apply migration, we need to migrate with the following artisan command:

php artisan migrate

Let’s create our pivot table. We need a migration file to create the order_books table. To create a migration file, give a command such as the following:

php artisan make:migration create_order_books_table --table=order_books --create

Open the migration file, which was created recently and located at database/migrations. We need to edit the up() function as follows:

  public function up()
  {
    Schema::create('order_books', function(Blueprint $table)
    {
      $table->increments('id');
      $table->integer('order_id');
      $table->integer('book_id');
      $table->integer('amount');
$table->decimal('price', 10, 2);
      $table->decimal('total', 10, 2);
    });  
}

To apply migration, we need to migrate with the following artisan command:

php artisan migrate

Our database design and models are finished. Now we need to code controllers and our application’s front pages.

Listing books

First, we need to list our products. To do that, we need to create a controller, which is namedBookController. Let’s create a file under app/http/controllers/ and save it with the name BookController.php. The controller code should look like the following:

<?php
class BookController extends BaseController{

  public function getIndex()
  {

    $books = Book::all();

    return View::make('book_list')->with('books',$books);

  }
}

The code simply fetches all the books from our books table and passes the data book_list.blade.php template with the $books variable. So we need to create a template file under app/http/controllers/, which is named as book_list.blade.php. Before doing this we need a layout page for our templates. Working with layout files is very helpful to manage html code. So first, we need a template file under app/controllers/, which is named main_layout.blade.php. The code should look like the following:

<!DOCTYPE html>
<html>
<head>
  <title>Awesome Book Store</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <!-- Bootstrap -->
  <link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="navbar navbar-inverse nav">
    <div class="navbar-inner">
        <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </a>
            <a class="brand" href="/">Awesome Book Store</a>
            <div class="nav-collapse collapse">
              <ul class="nav">
                  <li class="divider-vertical"></li>
                  <li><a href="/"><i class="icon-home icon-white"></i> Book List</a></li>
              </ul>
              <div class="pull-right">
                <ul class="nav pull-right">
                @if(!Auth::check())
                <ul class="nav pull-right">
                  <li class="divider-vertical"></li>
                  <li class="dropdown">
                    <a class="dropdown-toggle" href="#" data-toggle="dropdown">Sign In <strong class="caret"></strong></a>
                    <div class="dropdown-menu" style="padding: 15px; padding-bottom: 0px;">
                      <p>Please Login</a>
                        <form action="/user/login" method="post" accept-charset="UTF-8">
                          <input id="email" style="margin-bottom: 15px;" type="text" name="email" size="30" placeholder="email" />
                          <input id="password" style="margin-bottom: 15px;" type="password" name="password" size="30" />
                          <input class="btn btn-info" style="clear: left; width: 100%; height: 32px; font-size: 13px;" type="submit" name="commit" value="Sign In" />
                        </form>
                      </div>
                    </li>
                  </ul>
                @else
                <li><a href="/cart"><i class="icon-shopping-cart icon-white"></i> Your Cart</a></li>
                  <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">Welcome, {{Auth::user()->name}} <b class="caret"></b></a>
                        <ul class="dropdown-menu">
                            <li><a href="/user/orders"><i class="icon-envelope"></i> My Orders</a></li>
                            <li class="divider"></li>
                            <li><a href="/user/logout"><i class="icon-off"></i> Logout</a></li>
                        </ul>
                    </li>
                @endif
                </ul>
              </div>
            </div>
        </div>
    </div>
</div>

@yield('content')

  <script src="http://code.jquery.com/jquery.js"></script>
  <script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
  <script type="text/javascript">
  $(function() {
    $('.dropdown-toggle').dropdown();

    $('.dropdown input, .dropdown label').click(function(e) {
      e.stopPropagation();
    });
  });
  
  @if(isset($error))
    alert("{{$error}}");
  @endif

  @if(Session::has('error'))
    alert("{{Session::get('error')}}");
  @endif

  @if(Session::has('message'))
    alert("{{Session::get('message')}}");
  @endif

  </script>
</body>
</html>

The template file contains a menu, a login form, and some JavaScript code for the drop-down login form. We’ll use the file as our application’s layout template. We need to code our login and logout functions in the UserController.php file located at app/controllers. The login function should look like the following code:

<?php
class UserController extends BaseController {

  public function postLogin()
  {
    $email=Input::get('email');
    $password=Input::get('password');

    if (Auth::attempt(array('email' => $email, 'password' => $password)))
    {
        return Redirect::route('index');

    }else{

      return Redirect::route('index')
        ->with('error','Please check your password & email');
    }
  }

  public function getLogout()
  {
    Auth::logout();
    return Redirect::route('index');
  }
}

As shown in the following code, we need to add routes to our route file, routes.php, found under apps/http/:

Route::get('/', ['middleware' => 'guest', 'uses' => 'BookController@getIndex']);
Route::get('auth/register', 'AuthAuthController@getRegister');
Route::post('auth/register', 'AuthAuthController@postRegister');
Route::get('auth/login', 'AuthAuthController@getLogin');
Route::post('auth/login', 'AuthAuthController@postLogin');
Route::get('auth/logout', 'AuthAuthController@getLogout');

Creating a template file to list books

 

Now we need a template file to list books. As mentioned previously, we need to create a template file under resources/views/ and save it as book_list.blade.php. This file should look like the following:

@extends('main_layout')

@section('content')

<div class="container">
  <div class="span12">
    <div class="row">
      <ul class="thumbnails">
        @foreach($books as $book)
        <li class="span4">
          <div class="thumbnail">
            <img src="/images/{{$book->cover}}" alt="ALT NAME">
            <div class="caption">
              <h3>{{$book->title}}</h3>
              <p>Author : <b>{{$book->author->name}} {{$book->author->surname}}</b></p>
              <p>Price : <b>{{$book->price}}</b></p>
              <form action="/cart/add" name="add_to_cart" method="post" accept-charset="UTF-8">
                <input type="hidden" name="book" value="{{$book->id}}" />
                <select name="amount" style="width: 100%;">
                  <option value="1">1</option>
                  <option value="2">2</option>
                  <option value="3">3</option>
                  <option value="4">4</option>
                  <option value="5">5</option>
                </select>
              <p align="center"><button class="btn btn-info btn-block">Add to Cart</button></p>
            </form>
            </div>
          </div>
        </li>
        @endforeach
      </ul>
    </div>
  </div>
</div>

@stop

The template file has a form to add books to a cart. Now we need to code our functions in theCartController.php file located at app/http/controllers/. The content of CartController.phpshould look like the following:

<?php
class CartController extends BaseController {

  public function postAddToCart()
  {
    $rules=array(

      'amount'=>'required|numeric',
      'book'=>'required|numeric|exists:books,id'
    );

    $validator = Validator::make(Input::all(), $rules);

      if ($validator->fails())
      {
          return Redirect::route('index')->with('error','The book could not added to your cart!');
      }

      $member_id = Auth::user()->id;
      $book_id = Input::get('book');
      $amount = Input::get('amount');

      $book = Book::find($book_id);
      $total = $amount*$book->price;

       $count = Cart::where('book_id','=',$book_id)->where('member_id','=',$member_id)->count();

       if($count){

         return Redirect::route('index')->with('error','The book already in your cart.');
       }

      Cart::create(
        array(
        'member_id'=>$member_id,
        'book_id'=>$book_id,
        'amount'=>$amount,
        'total'=>$total
        ));

      return Redirect::route('cart');
  }


  public function getIndex(){

    $member_id = Auth::user()->id;

    $cart_books=Cart::with('Books')->where('member_id','=',$member_id)->get();

    $cart_total=Cart::with('Books')->where('member_id','=',$member_id)->sum('total');

    if(!$cart_books){

      return Redirect::route('index')->with('error','Your cart is empty');
    }
    
    return View::make('cart')
          ->with('cart_books', $cart_books)
          ->with('cart_total',$cart_total);
  }

  public function getDelete($id){

    $cart = Cart::find($id)->delete();

    return Redirect::route('cart');
  }

}

Our controller has three functions. The first of them is postAddToCart():

public function postAddToCart()
  {
    $rules=array(

      'amount'=>'required|numeric',
      'book'=>'required|numeric|exists:books,id'
    );

    $validator = Validator::make(Input::all(), $rules);

      if ($validator->fails())
      {
          return Redirect::route('index')->with('error','The book could not added to your cart!');
      }

      $member_id = Auth::user()->id;
      $book_id = Input::get('book');
      $amount = Input::get('amount');

      $book = Book::find($book_id);
      $total = $amount*$book->price;

       $count = Cart::where('book_id','=',$book_id)->where('member_id','=',$member_id)->count();

       if($count){

         return Redirect::route('index')->with('error','The book already in your cart.');
       }

      Cart::create(
        array(
        'member_id'=>$member_id,
        'book_id'=>$book_id,
        'amount'=>$amount,
        'total'=>$total
        ));

      return Redirect::route('cart');
  }

The function basically, at first, validates the posted data. The validated data checks the carts table for duplicate records. If the same book is not in the member’s cart, the function creates a new record in the carts table. The second function of the CartController is getIndex():

  public function getIndex(){

    $member_id = Auth::user()->id;

    $cart_books=Cart::with('Books')->where('member_id','=',$member_id)->get();

    $cart_total=Cart::with('Books')->where('member_id','=',$member_id)->sum('total');

    if(!$cart_books){

      return Redirect::route('index')->with('error','Your cart is empty');
    }
    
    return View::make('cart')
          ->with('cart_books', $cart_books)
          ->with('cart_total',$cart_total);
  }

The function fetches whole cart items, books’ information, and cart total and passes the data to the template file. The last function of the class is getDelete():

  public function getDelete($id){

    $cart = Cart::find($id)->delete();

    return Redirect::route('cart');
  }

The function basically finds from the carts table the given ID and deletes the record. We use the function to delete items from a cart. Now we need to create a template file. The file will show all cart information of members and also contains the order form. Save the file under resources/views/ ascart.blade.php. The content of cart.blade.php should look like the following:

@extends('main_layout')

@section('content')

<div class="container" style="width:60%">
  <h1>Your Cart</h1>
  <table class="table">
    <tbody>
      <tr>
        <td>
          <b>Title</b>
        </td>
        <td>
          <b>Amount</b>
        </td>
        <td>
          <b>Price</b>
        </td>
        <td>
          <b>Total</b>
        </td>
        <td>
          <b>Delete</b>
        </td>
      </tr>
      @foreach($cart_books as $cart_item)
        <tr>
          <td>{{$cart_item->Books->title}}</td>
          <td>
           {{$cart_item->amount}}
          </td>
          <td>
            {{$cart_item->Books->price}}
          </td>
          <td>
           {{$cart_item->total}}
          </td>
          <td>
            <a href="{{URL::route('delete_book_from_cart',array($cart_item->id))}}">Delete</a>
          </td>
        </tr>
      @endforeach
      <tr>
        <td>
        </td>
        <td>
        </td>
        <td>
          <b>Total</b>
        </td>
        <td>
          <b>{{$cart_total}}</b>
        </td>
        <td>
        </td>        
      </tr>
    </tbody>
  </table>
  <h1>Shipping</h1>
  <form action="/order" method="post" accept-charset="UTF-8">
    <label>Address</label>
    <textarea class="span4" name="address" rows="5"></textarea>
    <button class="btn btn-block btn-primary btn-large">Place order</button>
  </form>
</div>
@stop

Now we need to write our routes. The functions of the controller should just be accessible to members. So we can easily use Laravel’s built-in auth.basic filter:

Route::get('/cart', array('before'=>'auth.basic','as'=>'cart','uses'=>'CartController@getIndex'));
Route::post('/cart/add', array('before'=>'auth.basic','uses'=>'CartController@postAddToCart'));
Route::get('/cart/delete/{id}', array('before'=>'auth.basic','as'=>'delete_book_from_cart','uses'=>'CartController@getDelete'));

please note- here we are using array method not middlewares !

 

Taking orders

As you may remember, we’ve already created an order form in the cart.blade.php template file located at resoruces/views/. Now we need to process the order. Let’s code the OrderController.phpfile under app/http/controllers/:

<?php
class OrderController extends BaseController {

  public function postOrder()
  {
    $rules=array(

      'address'=>'required'
    );

  $validator = Validator::make(Input::all(), $rules);

      if ($validator->fails())
      {
          return Redirect::route('cart')->with('error','Address field is required!');
      }

      $member_id = Auth::user()->id;
      $address = Input::get('address');

       $cart_books = Cart::with('Books')->where('member_id','=',$member_id)->get();

       $cart_total=Cart::with('Books')->where('member_id','=',$member_id)->sum('total');

       if(!$cart_books){

         return Redirect::route('index')->with('error','Your cart is empty.');
       }

      $order = Order::create(
        array(
        'member_id'=>$member_id,
        'address'=>$address,
        'total'=>$cart_total
        ));

      foreach ($cart_books as $order_books) {

        $order->orderItems()->attach($order_books->book_id, array(
          'amount'=>$order_books->amount,
          'price'=>$order_books->Books->price,
          'total'=>$order_books->Books->price*$order_books->amount
          ));

      }
      
      Cart::where('member_id','=',$member_id)->delete();

      return Redirect::route('index')->with('message','Your order processed successfully.');
  }


  public function getIndex(){

    $member_id = Auth::user()->id;

    if(Auth::user()->admin){

      $orders=Order::all();

    }else{

      $orders=Order::with('orderItems')->where('member_id','=',$member_id)->get();
    }

    if(!$orders){

      return Redirect::route('index')->with('error','There is no order.');
    }
    
    return View::make('order')
          ->with('orders', $orders);
  }
}

The controller has two functions. The first of them is postOrder():

public function postOrder()
  {
    $rules=array(

      'address'=>'required'
    );

  $validator = Validator::make(Input::all(), $rules);

      if ($validator->fails())
      {
          return Redirect::route('cart')->with('error','Address field is required!');
      }

      $member_id = Auth::user()->id;
      $address = Input::get('address');

       $cart_books = Cart::with('Books')->where('member_id','=',$member_id)->get();

       $cart_total=Cart::with('Books')->where('member_id','=',$member_id)->sum('total');

       if(!$cart_books){

         return Redirect::route('index')->with('error','Your cart is empty.');
       }

      $order = Order::create(
        array(
        'member_id'=>$member_id,
        'address'=>$address,
        'total'=>$cart_total
        ));

      foreach ($cart_books as $order_books) {

        $order->orderItems()->attach($order_books->book_id, array(
          'amount'=>$order_books->amount,
          'price'=>$order_books->Books->price,
          'total'=>$order_books->Books->price*$order_books->amount
          ));

      }
      
      Cart::where('member_id','=',$member_id)->delete();

      return Redirect::route('index')->with('message','Your order processed successfully.');
  }

The function, first, validates the posted data. After successful validation, the function creates a new order on the orders table. The order table stores the member ID, shipping address, and total amount of the order. Then, the function attaches all cart items to the pivot table with their amount, price, and total amounts. In this way, the order items will not be affected by any price change. The function then deletes all items from the member’s cart. The second function of the controller isgetIndex():

public function getIndex(){

    $member_id = Auth::user()->id;

    if(Auth::user()->admin){

      $orders=Order::all();

    }else{

      $orders=Order::with('orderItems')->where('member_id','=',$member_id)->get();
    }

    if(!$orders){

      return Redirect::route('index')->with('error','There is no order.');
    }
    
    return View::make('order')
          ->with('orders', $orders);
  }

The function queries the database by looking at current user rights. If the current user has admin rights, the function fetches all the orders. If the current user has no admin rights, the function fetches just the user’s orders. So, now we need to write our routes. Add the following route code to app/http/routes.php:

Route::post('/order', array('before'=>'auth.basic','uses'=>'OrderController@postOrder'));
Route::get('/user/orders', array('before'=>'auth.basic','uses'=>'OrderController@getIndex'));

Our e-commerce application is almost done. Now we need to add a template file. Save the file under resources/views/ as cart.blade.php. The content of cart.blade.php should be like the following:

@extends('main_layout')
@section('content')
<div class="container" style="width:60%">
<h3>Your Orders</h3>
<div class="menu">
  <div class="accordion">
@foreach($orders as $order)
 <div class="accordion-group">
      <div class="accordion-heading country">
        @if(Auth::user()->admin)
        <a class="accordion-toggle" data-toggle="collapse" href="#order{{$order->id}}">Order #{{$order->id}} - {{$order->User->name}} - {{$order->created_at}}</a>
        @else
        <a class="accordion-toggle" data-toggle="collapse" href="#order{{$order->id}}">Order #{{$order->id}} - {{$order->created_at}}</a>
        @endif
      </div>
      <div id="order{{$order->id}}" class="accordion-body collapse">
        <div class="accordion-inner">
          <table class="table table-striped table-condensed">
            <thead>
              <tr>
              <th>
              Title
              </th>
              <th>
              Amount
              </th>
              <th>
              Price
              </th>
              <th>
              Total
              </th>
              </tr>
            </thead>   
            <tbody>
            @foreach($order->orderItems as $orderitem)
              <tr>
                <td>{{$orderitem->title}}</td>
                <td>{{$orderitem->pivot->amount}}</td>
                <td>{{$orderitem->pivot->price}}</td>
                <td>{{$orderitem->pivot->total}}</td>
              </tr>
            @endforeach
              <tr>
                <td></td>
                <td></td>
                <td><b>Total</b></td>
                <td><b>{{$order->total}}</b></td>
              </tr>
              <tr>
                <td><b>Shipping Address</b></td>
                <td>{{$order->address}}</td>
                <td></td>
                <td></td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
    </div>
@endforeach
</div>
</div>
@stop

The template file contains all the information about orders. The template is a very simple example of how to use pivot table columns. The pivot data comes as an array. So, we’ve used the foreach loop to use the data. You can store any data that you do not want to be affected by any changes in the database, such as price changes.

 

 

In this tutorial, we’ve built a simple e-commerce application. As you can see, thanks to Laravel’s template system and built-in authorization system, you can easily create huge applications. You can improve the application with third-party packages. the main package manager has been Composer. There is a huge library at http://packagist.org, which provides packages for image manipulating, social media APIs, and so on. The number of packages increase day-by-day, which are becoming, by default, Laravel compatible. We suggest that, before coding anything, you take a look at the Packagist website.

:) :)

Deven Rathore

Deven is an Entrepreneur, and Full-stack developer, Constantly learning and experiencing new things. He currently runs CodeSource.io and Dunebook.com.

Published by
Deven Rathore

Recent Posts

Flutter App Development: Essential Things You Should Know

Divided by mobile operating systems, companies have to develop their apps twice and roll them…

6 hours ago

7 Tips To Build Responsive & Dynamic Drupal Website For Your Business

For optimal user experience, consumers want responsive websites that are easy to use, multi-device friendly,…

2 days ago

OpenCart vs Magento: What You Should Choose in 2021

Users all over the world are faced with the problem of choosing a platform for…

1 week ago

Top 20 Android Open Source Projects

Reading codes and contributing to open source has been proven to be one of the…

3 weeks ago

Top 5 tools to proofread and edit essays with the help of software

Poor grammar and incorrect spelling can significantly lower the value of any literary work. Going…

6 hours ago

The Best 5 Career Advice for Web Design Students

Are you thinking of a career in web design but not sure where to start? The…

4 weeks ago