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.php
should 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 !
Hi, just following this but noticed that:
php artisan make:migartion create_authors_table –table=authors –create
should be:
php artisan make:migration create_authors_table –table=authors –create
(make:migration)
sorry for spelling mistake !
After running php artisan db:seed I was receiving:
[ReflectionException]
Class UsersTableSeeder does not exist
I had to do the following:
composer dump-autoload
php artisan db:seed
After this I received:
[SymfonyComponentDebugExceptionFatalErrorException]
– Not sure how to resolve that error though?
I dont think the dump autoload is needed in 5? Is it referring to a missing class? if so make sure the use appclass is entered on top. I noticed this was missing for alot of things.
I’m seen composer autodump-auto is used in a few places around the web (mostly tuts as I’m learning laravel at the moment). You were right about the class though (just been swatting namespaces this evening) and I was missing the use AppClass from at the top of the file – thanks!
you should using command line to make users seeder :
php artisan make:seeder UsersTableSeeder
then in namespace :
use AppUser;
Its a good tutorial to get started but it had a few typos and omissions. I should have noted them. One thing I would say regarding the last paragraph on passwords is that i think the statement needs to be clarified a bit. it sort of implies that the passwords are also salted with the application key and that users should worry about figuring a way to store passwords, which may lead to additional security issues.
I think it should be noted that the passwords are hashed and salted via bCrypt and persons shoudl read up on how it works but it uses a per password salt not the single application key to salt the passwords. I’m not sure if thats what you meant but it was in the same paragraph.
The application key as I understand it is for other things like encrypting sessions etc. Also while users should know of how the passwords are hashed and salted, they should not be tempted into creating thier own password hashing/encryption algoriithm. bCrypt is solid and if a user wants to make it tougher they can increase the rounds Hash::make(‘thisisthepasswrd’, array(’rounds’ => 15)).
Otherwise thanks for the tut, good way for me to get my feet wet learning Laravel.
ok point noted
There seems to be an inconsistency between the routes file, the user and auth controllers and the blade file when it comes to logins.
“We need to code our login and logout functions in the UserController.php file located at app/controllers.”
Yes, the functions are in the UserController but in the routes file they point to the Auth/AuthController. Also the blades file refer to /user/login but the routes file refer to auth/login.
Also the routes file has this: Route::get(‘auth/login’, ‘AuthAuthController@getLogin’); and this function isnt defined anywhere (unless it is being extended from another class)..
So I think either the routes file should be saying ‘UserController@postLogin… or the login functions should be in the Auth controller. Then the blade file should be pointing to the correct one (either user/login or auth/login)..
i have missed one thing here i am not using built in auth function of laravel
Page 5 Books.php You have : return $this->belongsTo(‘Author’);
It seems to have problems recognizing Author so one may have to do this: ‘AppAuthor’ (or something similar. Also since its using relationships does it need a foreign key? It may need to end up looking like
return $this->belongsTo(‘AppAuthor’,’id’). (Only way I could have gotten it to work).
Cart.php (AppBooks may be needed).
Page 9. refers to the orders but says to save blade file as cart.blade.php
Last major thing I had problem with is the pivot.
It seems that the orders and books table having a many-to-many relationship by default will attempt an insert using the table name book_order. I got a ” Base table or view not found: 1146 Table” error. I did some reading and Laravels documentation gives a clue: ” The role_user table is derived from the alphabetical order of the related model names” So I created a table called book_order and it worked.
So in case anyone else has these issues this may help.
thanks again
may i know , what version of laravel in this tutorial?
laravel 5
5.1?
yes !
Done a tutorial , but after i ran , get too may errors, are you sure this tutorial using laravel 5.1?
please share Errors you got !
FatalErrorException in Model.php line 827:Class ‘Author’ not found
sorry for late reply ! lets solve your problem
TokenMismatchException in VerifyCsrfToken.php line 53:
will fix that ! btw thanks
in laravel5 we need to use make command instead of generate
I fail to see how this is an “e-commerce” tutorial when this “tutorial” doesn’t even cover charging the users card. Did I miss something here?
try out this tut https://dunebook.com/easily-develop-a-ecommerce-website-with-laravel/
Thank you for the link, Deven!
i have an error after seeding class user not found any help noting that there are too many errors in this tut
you need to add, use AppUser; above class at seeder file
hello, how is your AuthAuthController wrote?
UserInterface, RemindableInterface interfaces were removed from Laravel 5.0, how can you still be using them?
Source: https://laravel.com/docs/5.0/upgrade
What happens to the cart.blade.php in last page 4
Done with tutorial, but ‘Add to Cart’ button is not working.(problem in routes.php file)
I just finished this tutorial, and I integrated this e-commerce store with a working Stripe payment system, among some other bug fixes using Laravel 5.2. Who ever is the owner or editor of this website, would you want to upload a part 2 to this tutorial if I uploaded my project to Github using my code?
sure . we are intrested .. thankuuh so much . . shoot an email to hyguyz @outlook.com
There, I sent you an email
yeah. sent in my email [email protected]
thank you so much ,shoot an email [email protected]
please send me at [email protected]
Confused: why doesn’t he used a pivot table called book_order where just the order id and the book id are listed?
Wouldn’t their need to be a pivot table between Cart and Book since just like the relationship/pivot table between Order and Book, a Cart can have multiple books in it and a Book can be in multiple carts?
checkout code of this tutorial https://github.com/hydrogen11/store_ex
I have made a full e-commerce store using the shopping cart method from this tutorial: Here is the website:
http://davidtrushkov.com/store/
and here is the Github code
https://github.com/davidtrushkov/store
thanks , for sharing @davidtrushkov:disqus
Thanks a lot, that was a great help!
Awesome!!!
Thanks for that man
Much Appreciated
Really Good Work .. One of the most valuable comment
There is no administration page to allow the administrator to log in to add products, categories and others?
how to create migration file for the Book?
please upload source code to git.
pls put this command – php artisan make:migration create_books_table –table=books –create
It should be php artisan make:migration create_carts_table –table=carts –create
Hi. If I won’t put the order price on table, just the product and quantity, any idea how can we get the total price from Model ?
please get this project thank you !
[email protected]
Interface ‘IlluminateAuthUserInterface’ not found getting this error after running php artisan db:seed.
We created a similar article for Laravel enthusiasts who want to build a Laravel cart from grounds-up. Check https://therightsw.com/laravel-ecommerce-website-guidelines/
Please I can have the source code of the project?
my email : [email protected]
Its a good tutorial for beginners. but there are some mistakes like you give this “So first, we need a template file under app/controllers/, which is named main_layout.blade.php”. but its not correct to create templates in controllers folder. so document the tutorial according to the standards.
Symfony \ Component \ Debug \ Exception \ FatalThrowableError (E_ERROR)
Class ‘App\Http\Controllers\Book’ not found