Create an E-Commerce Website with laravel 5.2

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-mailspassword: This is the column for storing a member’s passwordname: This is the column for storing a member’s name and surnameadmin: 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' => '[email protected]',
'password' => Hash::make('password'),
'name' => 'John Doe',
'admin'=>0
));
User::create(array(
'email' => '[email protected]',
'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.
:) :)