Create Laravel Store with Vue

Ref: https://blog.pusher.com/ecommerce-laravel-vue-part-1/

In this article, we will cover how you can use Laravel to build a simple e-commerce application. After this tutorial, you should know how to use Laravel and Vue to make a web application and understand the basics of making an online store.

With the advent of the internet, many regular things became faster and easier. One of the things that improved is commerce. Commercial activities carried out on the web are known as e-commerce.

E-commerce applications make sales of goods and services over the internet possible. If you use the internet often, chances are you have come across one or even used one at some point.

Introduction
As we mentioned earlier, an e-commerce application makes selling goods and services online very convenient. It provides a listing of the products the seller wishes to sell showing their prices, then a page where you can see all the details of the single product selected, and finally, where to pay for the product and set how you wish to receive it.

With this in mind, we know that to have a useful e-commerce application, we’d need to develop the following:

A listing page to view all our products.
A single page to view product information.
A checkout page where the buyer can enter a delivery address and pay.
A simple dashboard for a buyer to see all purchased products, and know if they have shipped.
A way for the seller to add products to sell.
A way for the seller to see which orders users placed.
A way for the seller to show a product has been shipped to the user.
A way for the seller to see and update all product information.
Planning the structure of the application
From our breakdown above, you may see that this application will have two user types:

Administrator – The owner of the store.
Buyer – The person who wants to buy a gift for a friend.
You definitely know that the application will also have products that need to be stored. These products will be ordered and you need a way to store and track those orders. These would form the basis of any e-commerce platform.

The basic details we need to store in the different parts:

The basic operations we need the app to carry out, and where these are handled, are:

If you want to go a little deeper, you can consider adding categories, tags, warehouse items, more user types and many other things. However, we will not be considering them for this guide, but you should definitely try it on your own.

A good way to learn is by practicing. You can exercise your mind by doing the task in the previous paragraph.
Creating the application
We are going to use the Laravel CLI to make a new Laravel application. To create a new Laravel application, run the following command:

Then you can cd into the project we just created. The Laravel related commands we run throughout the article needs to be run from the root of the Laravel project.

Creating the models for the application
Models in Laravel provide a very convenient way to interact with the database. They provide methods for all the basic operations you need to run for your database table.

Let’s make the models that will interact with our database and hold business logic. New Laravel installations come with the User model out of the box, which can be found in app directory so let’s make the other two models:

We have added the -mr flag to the make:model command so that it will generate the accompanying migration and controller for the model.

Next open the app/User.php file and replace the contents with the following:

We are using SoftDeletes to allow us to mark a database record as deleted without actually deleting it completely. This is useful if you want to be able to restore the data.

We also have an array – $fillable, with the column names we want to mass assign on the users table. Mass assignment happens when we call our User model statically and pass an array to its create method.

Open app/Product.php file and edit as follows:

The Product model is quite similar to the User model. It has the $fillable array and also an orders method for establishing a relationship with orders placed on the application.

Now, open app/Order.php file and edit as follows:

The Order model looks slightly different from the other two but is essentially the same thing. We just established a different kind of relationship – belongsTo that shows which user made an order or which product was ordered.

Defining the migrations for the application
Migrations are a good way to create and maintain your application’s database. It essentially defines how tables should be created or modified.

Migrations are useful because they help you manage the database tables, columns and keys. You can share migration files instead of raw SQL, and because migration files are run chronologically, they make it easy to work with git, so it’s great for teams.

Open the create_users_table migrations file in the database/migrations directory and replace the content with the following:

Laravel is quite readable and you can probably figure out what is going on by reading the code. We defined which columns should exist in the table and their attributes.

There are many methods in the Blueprint class for migrations. You can read more here.

Next, open the create_products_table migrations file in the database/migrations directory and replace the code with the following:

Finally, open the create_orders_table migrations file in the database/migrations directory and replace the contents with the following:

Creating seeders for the application
Seeders are an excellent way to pre-populate our database with dummy data. We are going to use the seeder class to create the user account for our administration.

Create a seeder class by running the command below:

Now, open the file UserTableSeeder.php at the database/seeds directory and replace the content with the following:

The seeder class above will create a new admin user in the database.

Recall that when we defined the User model, we did not include is_admin in the fillable column. The reason is that we do not want anyone who tries to spoof our application to create an administrator user. This is why we had to create a user instance here so we can access all the columns from the user table.
Make another seeder class for our products table:

Open the database/seeds/ProductTableSeeder.php file and replace the contents with the following:

The data we populated the database with is from here and is for sample educational purposes. You may require permissions to actually use the images.
When you are done making the seeder, you need to edit the database/seeds/DatabaseSeeder.php, which actually invokes the seeders:

Now, when we execute the command to seed our database the DatabaseSeeder class is called and it calls the run which in turn class the seeder classes we had setup to run.

You can learn more about seeders here.
Creating the database for our application
We have defined everything we need our database to have. Now, we need to actually define the database itself. We are going to use SQLite for this guide, but you can any database you like. You should use a non-file based database like MySQL if in a production environment (NOTE: I’m going to use mysql instead).

If you want to use sqlite, Create a database file at database/database.sqlite (NOTE: I’m going to use mysql instead). Next, open your .env file and replace the following lines:

with

That is all for our database setup. Run the migrations to create the database tables for our application and seed it:

Defining and securing our endpoints
Our application uses Laravel and Vue to create the best application experience. This means we would need to define APIs to provide our Vue components with data.

Laravel, by default, has support for web and API routes. Web routes handle routing for dynamically generated pages accessed from a web browser, while API routes handle requests from clients that need a response in mostly JSON or XML format.

Our application will have APIs for most requests. We need to secure our APIs to ensure only authorised users will access it. For this, we will use Laravel Passport.

Install passport
To install passport, run the following command:

Laravel Passport comes with it’s own migrations, run the migrations using the following command:

Next, run the passport installation command to create the necessary keys for securing your application:

The above command will create encryption keys needed to generate secure access tokens plus “personal access” and “password grant” clients, which will be used to generate access tokens.

After the installation, you need to use the Laravel Passport HasApiToken trait in the User model. This trait will provide a few helper methods to your model, which allow you to inspect the authenticated user’s token and scopes.

Open the app/User.php file and edit as follows:

Next, call the Passport::routes method within the boot method of your AuthServiceProvider. This method will register the routes necessary to issue the tokens your app will need:

In the app/Providers/AuthServiceProvider.php file update as follows:

Finally, in your config/auth.php configuration file, you should set the driver option of the api authentication guard to passport.

That’s all for Laravel Passport.

Conclusion
So far, we have set up our application by defining all the models we need. We have also added migrations for our database, and lastly, we added Laravel Passport for handling authorization for our APIs.

The next thing we will look at is implementing the controllers to handle the different kinds of request we are going to make to the application and the views to interact with the application. Continue to part two.

In the previous chapter, we set up our application’s migrations and models, and installed Laravel Passport for authentication. We also planned what the application will look like. In this chapter, we will implement the controllers and handle all requests to our application.

Prerequisites
To continue with this part, please go through the first part of the series first and make sure you have all the requirements from that part.

Building our controllers
In the first chapter, we already defined our models and their accompanying controllers. These controllers reside in the app/Http/Controllers directory. The User model, however, does not have an accompanying controller, so we are going to create that first. Run the following command:

Now, open the created controller file app/Http/Controllers/UserController.php and replace the contents with the following:

Above we defined some class methods:

index() – returns all users with their orders.
login() – authenticates a user and generates an access token for that user. The createToken method is one of the methods Laravel Passport adds to our user model.
register() – creates a user account, authenticates it and generates an access token for it.
show() – gets the details of a user and returns them.
showOrders() – gets all the orders of a user and returns them.
We used Laravel’s Route-Model Binding to automatically inject our model instance into the controller. The only caveat is that the variable name used for the binding has to be the same as the one defined in the route as well.

Next, open the app/Http/Controllers/ProductController.php file and replace the contents with the following:

In the ProductController above we defined seven methods:

index() – fetches and returns all the product records.
store() – creates a product record.
show() – fetches and returns a single product.
uploadFile() – uploads the image for a product we created and returns the url for the product.
update() – updates the product record.
updateUnits() – adds new units to a product.
delete() – deletes a product.
Next, open the app/Http/Controllers/OrderController.php file and replace the content with the following:

In the OrderController above we have six methods:

index() – fetches and returns all the orders.
deliverOrder() – marks an order as delivered.
store() – creates an order.
show() – fetches and returns a single order.
update() – updates the order.
destroy() – deletes an order.
That’s it for our controllers. We have created the controller according to the specifications we laid out in the first part. Next thing we need to do is define our API routes.

Defining our application’s routes
Now that we have fully defined all the requests we would like to make to our application, let’s expose the APIs for making these requests. Open routes/api.php file and replace the content with the following:

Putting our route definitions in the routes/api.php file will tell Laravel they are API routes so Laravel will prefix the routes with a /api in the URL to differentiate them from web-routes.

Adding the auth:api middleware ensures any calls to the routes in that group must be authenticated.

A thing to note is, using the resource method on the Route class helps us create some additional routes under the hood without us having to create them manually. Read about resource controllers and routes here.

To see the full route list, run the following command: $ php artisan route:list

Since we will build the front end of this application in Vue, we need to define the web routes for it. Open the routes/web.php file and replace the contents with the following:

This will route every web request to a single entry point, which will be the entry for your Vue application.

Setting up Vue for the frontend
Vue is a progressive framework for building user interfaces. Unlike other monolithic frameworks, Vue is designed from the ground up to be incrementally adoptable – vuejs.org
Laravel comes with Vue bundled out of the box, so all we need to do to get Vue is to install the node packages. Run the following command:

Next, we will need VueRouter to handle the routing between the different components of our Vue application. To install VueRouter run the command below:

Next, let’s make the landing view file, which would mount our Vue application. Create the file resources/views/landing.blade.php and add the following code:

In the code above, we have the HTML for our application. If you look closely, you can see the app tag. This will be the entry point to our Vue application and where the components will be loaded.

Since we will use app.js to set up our VueRouter, we still need to have Bootstrap and Axios compiled. The import for Bootstrap and Axios is in the bootstrap.js file so we need to compile that.

Edit the webpack.mix.js file so it compiles all assets:

the webpack.mix.js file holds the configuration files for laravel-mix, which provides a wrapper around Webpack. It lets us take advantage of Webpack’s amazing asset compilation abilities without having to write Webpack configurations by ourselves. You can learn more about Webpack here.
Set up the homepage for the Vue application. Create a new file, resources/js/components/Home.vue, and add the following code to the file:

The code above within the opening and closing template tag we have the HTML of our Vue component. In there we loop through the contents of products and for each product we display the image, name, id, price and units available. We use the v-html attribute to render raw HTML, which makes it easy for us to use special characters in the product name.

In the script tag, we defined the data(), which holds all the variables we can use in our template. We also defined the mounted() method, which is called after our component is loaded. In this mounted method, we load our products from the API then set the products variable so that our template would be updated with API data.

In the same file, append the code below to the bottom:

In the code above, we have defined the style to use with the welcome component.

According to the Vue documentation: When a <style> tag has the scoped attribute, its CSS will apply to elements of the current component only. This is similar to the style encapsulation found in the Shadow DOM. It comes with some caveats but doesn’t require any polyfills.
Next create another file, resources/js/components/App.vue. This will be the application container where all other components will be loaded. In this file, add the following code:

In the Vue template above we used some Vue specific tags like router-link, which helps us generate links for routing to pages defined in our router. We also have the router-view, which is where all the child component pages will be loaded.

Next, below the closing template tag, add the following code:

In the script definition we have the methods property and in there we have three methods defined:

setDefaults() – sets the name of the user when the user is logged in as well as the type of user logged in.
change()– checks the current login status anytime it is called and calls the setDefaults method.
logout() – logs the user out of the application and routes the user to the homepage.
In our router-view component, we listen for an event loggedIn which calls the change method. This event is fired by our component anytime we log in. It is a way of telling the App component to update itself when a user logs in.

Next create the following files in the resources/js/components directory:

Admin.vue
Checkout.vue
Confirmation.vue
Login.vue
Register.vue
SingleProduct.vue
UserBoard.vue
These files would hold all the pages myStore would have. They need to be created prior to setting up VueRouter, so that it won’t throw an error.

To set up the routing for our Vue single page app, open your resources/js/app.js file and replace the contents with the following code:

Above, we have imported the VueRouter and we added it to our Vue application. We defined routes for our application and then registered it to the Vue instance so it is available to all Vue components.

Each of the route objects has a name, which we will use to identify and invoke that route. It also has a path, which you can visit directly in your browser. Lastly, it has a component, which is mounted when you visit the route.

On some routes, we defined meta, which contains variables we would like to check when we access the route. In our case, we are checking if the route requires authentication and if it is restricted to administrators or regular users only.

We set up the beforeEach middleware on the router that checks each route before going to it. The method takes these variables:

to – the route you want to move to.
from – the current route you are moving away from.
next – the method that finally moves to a defined route. When called without a route passed, it continues the navigation. If given a route, it goes to that route.
We use beforeEach to check the routes that require authentication before you can access them. For those routes, we check if the user is authenticated. If the user isn’t, we send them to the login page. If the user is authenticated, we check if the route is restricted to admin users or regular users. We redirect each user to the right place based on which access level they have.

Now add the following lines to the end of the app.js file

This instantiates the Vue application. In this global instance, we mount the App component only because the VueRouter needs it to switch between all the other components.

Now, we are ready to start making the other views for our application.

Conclusion
In this part, we implemented the controller logic that handles all the requests to our application and defined all the routes the application will use. We also set up Vue and VueRouter to prepare our application for building the core frontend.

In the next chapter of this guide, we are going to build the core frontend of the application and consume the APIs. See you in the next part.

Making the authentication pages
In the previous part, we created all the view files for our Vue application, although we did not add content to all of them. Let’s start with the login and register pages.

Open the resources/js/components/Login.vue file and paste in the following code:

Above we have a login form. We don’t have much functionality yet so let’s append the following code to the same file to add some Vue scripting:

Above we have a handleSubmit method that is fired when the form is submitted. In this method we attempt to authenticate using the API. If the authentication is successful, we save the access token and user data in localStorage so we can access them across our app.

We also emit a loggedIn event so the parent component can update as well. Lastly, we check if the user was sent to the login page from another page, then send the user to that page. If the user came to login directly, we check the user type and redirect the user appropriately.

Next, open the resources/js/components/Register.vue file and paste in the following:

Above we have the HTML for the registration form. Let’s add the script for the component below the closing template tag:

NOTE: I added a check for the password and the confirmation characters length. It should be more than 5 characters.
The register component operates similarly to the login component. We send the user data to the API for authentication and if we get a favourable response we save the token and user to localStorage.

Making the marketplace pages
We had already defined the homepage in the last chapter and returned a list of available products. Now, we are going to make all the other store pages.

Open the resources/js/components/SingleProduct.vue file and paste in the following code:

NOTE: USE backtick (`) INSTEAD OF apostroph (‘) ON let url VARIABLE TO PARSE ${this.$route.params.id}
Above we have the product as a data attribute, which we use to display information on the page like we did in the Home.vue file.

In the components script we defined Vue’s beforeMount method and fetched the product information there. beforeMount is called before the component is rendered, so it fetches the necessary data for rendering the component. If we get the data after the component has mounted, we would have errors before the component updates.

Next, open the resources/js/components/Checkout.vue file and paste the following code for the HTML template and style:

Above we defined the beforeMount method where we fetch product information. Then we have the mounted method where we check authentication status. In the methods property, we defined the checkUnits method that checks how many units the user wants to order, and then we define the placeOrder method that places the order.

Next, open the resources/js/components/Confirmation.vue file and paste the following code:

This component displays a simple thank you message and provides a link for the users to navigate to their dashboard to see the orders they have placed and the status of these orders. Let’s create the user dashboard next.

Creating the user dashboard
The user dashboard is where the users can see all their orders. Open the resources/js/components/UserBoard.vue file and paste in the following code for the template and style:

In the code above, we fetch all the user’s orders before the component is mounted, then loop through them and display them on the page.

Creating the admin dashboard
The admin dashboard is where new products are added, existing products modified and orders are set as delivered.

For the admin board, we will use four different components, which we will mount based on the url a user is accessing. Let’s see that in action. Open the resources/js/components/Admin.vue file and paste in the following:

In the code above, we import and register four components, which we have not yet created. They’ll be used as components inside Admin.vue parent component.

In our template, we defined the navigation for switching between the components. Each navigation link calls the setComponent method and then passes a value to it. The setComponent method just sets the component using a switch statement.

Let’s create the first component for the Admin component. Create the Main.vue file in resources/js/components/admin directory and paste the following into the file:

In the code above we are calling the APIs for users, orders and products, and returning their data.

Create the Orders.vue file in resources/js/components/admin and paste the following into the file:

In beforeMount we fetch all the orders placed before the component is rendered.

When the Deliver button is clicked, the deliver method is fired. We call the API for delivering orders. To get the change to reflect on the page instantly, we call [$forceUpdate](https://vuejs.org/v2/api/#vm-forceUpdate).

Create the Users.vue file in resources/js/components/admin and paste in the following code:

Above we fetch all the user data and then display it on the page.

Next, create the Products.vue file in resources/js/components/admin and paste the following template code:

In the methods property we defined the following methods:

newProduct() – called when we want to initiate a new local product object.
endEditing() – called when we are done editing a product.
addProduct() – called when we are want to add a new product.
We imported a ProductModal component, which we will create next. The modal will be used to edit an existing or create a new product. Double clicking on a product listed fires up the modal for editing the product.

Create the ProductModal.vue file in resources/js/components/admin and paste in the following template and style code:

When the modal receives a product’s data, it pre-fills each field with the data. When we attach an image and submit the modal’s form, it is uploaded and the url for the image is returned to us.

We update the image attribute of the product with the url, then emit a close event and return the product with it. If no image is attached, we emit a close event and return the product data along with it.

This modal component is an example provided in Vue documentation here

Payments
There are many payment options for e-commerce platforms. You choose depending on your needs and what is available in your country. Many popular payment processors like Stripe have excellent guides on integrating into a JavaScript or PHP application which you can use. This tutorial won’t cover that though, you can take it as an exercise for practise.

Building our application
We are done building our application. The next thing to do will be to compile our Vue application and serve our Laravel backend. Run the command to build the application.

Admin user:
email: admin@admin.com
name: Admin
password: secret

Create/Register a new user:
email: advcha@yahoo.com
name: Satria
password: satria

Leave a Reply

Your email address will not be published. Required fields are marked *