AppDividend
Latest Web Development Tutorials

Laravel 5 VueJS Tutorial

Laravel 5.4 Vue.js 2.0 Tutorial

12,726

Laravel 5 VueJS Tutorial is today’s main topic. Laravel is PHP’s fastest growing Framework with its ease of use, scalability, and flexibility. VueJS is the fastest growing Front end Library in Javascript community. Laravel is providing VueJS support out of the box. So let us up and running with Laravel VueJS tutorial.

Summary

Laravel 5 and VueJS Tutorial will walk through the exercise of how you can set up the development environment with each other, and we are creating Simple CRUD Application.

Purpose

One possible reason I am writing this is showcase how Laravel PHP Framework and modern client-side Javascript frameworks (Vue.js) can all play nicely together.

Requirements 

For learning Vue.js, I suggest to my this article Vuejs Tutorial With Example. It will guide you to learn fundamentals of Vue.js 2.0. If you want to know how a router works on Vue.js, then check out my this tutorial How To Use vue-router in VueJS.

We are using Laravel 5.4 and Vue.js 2.0. So technically It is the Laravel 5.4 Vue.js Tutorial.

If you want to learn Laravel CRUD example then check out my this tutorial Laravel 5.4 Crud Example From Scratch

Laravel 5 VueJS Tutorial




Step 1: Create the project Laravel Vue js Tutorial.

Type the following command in your terminal.

composer create-project laravel/laravel laravelvuejstutorial --prefer-dist

After installing the project, go to the project folder and type following command in your terminal.

npm install

It will install all the JavaScript dependencies regarding VueJS. It will install laravel-mix, which you can think of as kind of module bundle like webpack.

Now, setup a database in MySQL and also we need to configure in Laravel. So in your project root, there is a .env file, and in that file, you need to configure your username, DB name, and password. After configured, type following command in your terminal.

php artisan migrate

If you will navigate to resources  >> assets  >>  js  >>  components, you will see the Example.vue component is there, so basically, Laravel provides VueJS support out of the box, though we can use other JS frameworks like ReactJS or AngularJS. This component is required in the outer JS file called app.js. This file will be compiled by Laravel Mix. 

I have removed the comments provided by Laravel, so that app.js file will look like this.

// app.js

require('./bootstrap');

window.Vue = require('vue');

Vue.component('example', require('./components/Example.vue'));

const app = new Vue({
    el: '#app'
});

We need to install some other dependencies as well for the running VueJS library smoothly and also we need to use vue-router for routing our application.

npm install --save-dev vue-axios vue-loader vue-router vue-template-compiler

Step 2: Edit the default configuration.

We are going to change this file by the following code.

// app.js

import Vue from 'vue';

import VueRouter from 'vue-router';
Vue.use(VueRouter);

import VueAxios from 'vue-axios';
import axios from 'axios';
Vue.use(VueAxios, axios);

const router = new VueRouter({ mode: 'history'});
new Vue(Vue.util.extend({ router })).$mount('#app');

Here, we have imported vue, vue-router and vue-axios, axios libraries for our application.

Created the router object and set the mode history so that we can get rid of the pound (#) on every route.

Now, switch to resources  >>  views  >>  welcome.blade.php file and replace the following code with that file.

// welcome.blade.php

<!doctype html>
<html lang="{{ app()->getLocale() }}">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Laravel Vue CRUD Application</title>
        <link href="{{asset('css/app.css')}}" rel="stylesheet" type="text/css">
    </head>
    <body>
        <div id="app">
        </div>
         <script>
           window.Laravel = <?php echo json_encode([
               'csrfToken' => csrf_token(),
                    ]); ?>
          </script>
        <script src="{{asset('js/app.js')}}"></script>
    </body>
</html>

We need to create one Vue component inside resources  >>  assets  >>  js directory and call this component as an App.vue.

// App.vue

<template>
    <div class="container">
        <div>
            <transition name="fade">
                <router-view></router-view>
            </transition>
        </div>
    </div>
</template>

<style>
    .fade-enter-active, .fade-leave-active {
      transition: opacity .5s
    }
    .fade-enter, .fade-leave-active {
      opacity: 0
    }
</style>

<script>

    export default{
    }
</script>

This component will work as a container of our application. When routes of our VueJS application changes according to that different components will be rendered with in <router-view><router-view> tag.

We need to include this component into our app.js file and pass it to the Vue object while creating an instance.

// app.js

import App from './App.vue';

new Vue(Vue.util.extend({ router }, App)).$mount('#app');

Go to the terminal and type following command.

npm run watch

If you see any error, please first check if there is dependency which needs to be installed at first place.

Step 3: Create routes with vue-router for our application.

In app.js file, we also include the Example.vue component because we are going to create routes for our application. So, first create an array of routes in app.js file.

// app.js

const routes = [
  {
      name: 'Example',
      path: '/',
      component: Example
  }
];

const router = new VueRouter({ mode: 'history', routes: routes});
new Vue(Vue.util.extend({ router }, App)).$mount('#app');

Here, I have created an array of routes and pass it to the router object. So, your whole app.js file will look like this.

// app.js

import Vue from 'vue';

import VueRouter from 'vue-router';
Vue.use(VueRouter);

import VueAxios from 'vue-axios';
import axios from 'axios';
Vue.use(VueAxios, axios);

import App from './App.vue';
import Example from './components/Example.vue';

const routes = [
  {
      name: 'Example',
      path: '/',
      component: Example
  }
];

const router = new VueRouter({ mode: 'history', routes: routes});
new Vue(Vue.util.extend({ router }, App)).$mount('#app');

Now, if everything is set up correctly then type the following command in your terminal.


php artisan serve

It will start the server on port 8000. So in chrome switch to this URL: http://localhost:8000

Laravel and VueJS Tutorials

Step 4: Create Laravel Backend For Our Application.

Next step would be from moving VueJS to Laravel and create a backend for our project. We can use Web routes or API routes and for this project let us stick with web routes, so we need to put all of our routes in the routes  >>  web.php file.

First, we are going to perform CRUD operations on items. So first let us define the schema for it. Then we will create controller and routes.

Go to your command line and type following command. Make sure that, you are at the root of our project folder.

php artisan make:model Item -m

It will create two files.

  1. Model file.
  2. Migration file.

Go to migration file in the database  >>  migrations  >>  create_items_table and copy the following code into it.

<?php

// create_items_table

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateItemsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('items', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->integer('price');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('items');
    }
}

Go to the terminal and type the following command.

php artisan migrate

It creates the items table in the database. Also, one model file is created which is in the app folder.

It is time to create one resource controller called ItemController by the typing following command.

php artisan make:controller ItemController --resource

This ItemController contains all its methods of CRUD operations. We just need to put the code in it. I am right now putting the whole file with all the operations in it.

<?php

// ItemController.php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Item;

class ItemController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $items = Item::all();
        return response()->json($items);
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $item = new Item([
          'name' => $request->get('name'),
          'price' => $request->get('price')
        ]);
        $item->save();
        return response()->json('Successfully added');
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        $item = Item::find($id);
        return response()->json($item);
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        $item = Item::find($id);
        $item->name = $request->get('name');
        $item->price = $request->get('price');
        $item->save();

        return response()->json('Successfully Updated');
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
      $item = Item::find($id);
      $item->delete();

      return response()->json('Successfully Deleted');
    }
}

We also need to create protected $fillable field in Item.php file otherwise ‘mass assignment exception‘ will be thrown.

<?php

// Item.php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Item extends Model
{
    protected $fillable = ['name', 'price'];
}




The last step would be to register the routes in routes >> web.php file.

<?php

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
 return view('welcome');
});
Route::resource('items', 'ItemController');

Step 5: Make three components and register with App component.

All of our Backend is almost done. Now, if we switch to front end in Vue.js, we need to create three components, and then we include it in an app.js file to register the routes and is good to go.

Create following components inside resources  >>  assets  >>  js  >>  components.

  1. CreateItem.vue
  2. EditItem.vue
  3. DisplayItem.vue
// CreateItem.vue

<template>
  <div>
    <h1>Create An Item</h1>
    <form v-on:submit.prevent="addItem">
      <div class="row">
        <div class="col-md-6">
          <div class="form-group">
            <label>Item Name:</label>
            <input type="text" class="form-control" v-model="item.name">
          </div>
        </div>
        </div>
        <div class="row">
          <div class="col-md-6">
            <div class="form-group">
              <label>Item Price:</label>
              <input type="text" class="form-control col-md-6" v-model="item.price" />
            </div>
          </div>
        </div><br />
        <div class="form-group">
          <button class="btn btn-primary">Add Item</button>
        </div>
    </form>
  </div>
</template>
<script>
  export default {
    data(){
        return{
          item:{}
        }
    },
    methods: {
      addItem(){
        let uri = 'http://localhost:8000/items';
        this.axios.post(uri, this.item).then((response) => {
          this.$router.push({name: 'DisplayItem'})
        })
    }
  }
}
</script>

Here, I have defined the template which is basic Item creation form. In Javascript, I have to define item object and post method to post the data to the Laravel backend server.

Now, this file needs to be included in the app.js file to register the routes to be able to see the form.

Okay, now create one another component called DisplayItem.vue in the components folder.

// EditItem.vue

<template>
    <div>
        <h1>Items</h1>

        <div class="row">
          <div class="col-md-10"></div>
          <div class="col-md-2">
            <router-link :to="{ name: 'CreateItem' }" class="btn btn-primary">Create Item</router-link>
          </div>
        </div><br />

        <table class="table table-hover">
            <thead>
            <tr>
                <td>ID</td>
                <td>Item Name</td>
                <td>Item Price</td>
                <td>Actions</td>
            </tr>
            </thead>

            <tbody>
                <tr v-for="item in items">
                    <td>{{ item.id }}</td>
                    <td>{{ item.name }}</td>
                    <td>{{ item.price }}</td>
                    <td><router-link :to="{name: 'EditItem', params: { id: item.id }}" class="btn btn-primary">Edit</router-link></td>
                    <td><button class="btn btn-danger" v-on:click="deleteItem(item.id)">Delete</button></td>
                </tr>
            </tbody>
        </table>
    </div>
</template>

<script>

    export default {
        data(){
            return{
                items: []
            }
        },

        created: function()
        {
            this.fetchItems();
        },

        methods: {
            fetchItems()
            {
              let uri = 'http://localhost:8000/items';
              this.axios.get(uri).then((response) => {
                  this.items = response.data;
              });
            },
            deleteItem(id)
            {
              let uri = `http://localhost:8000/items/${id}`;
              this.items.splice(id, 1);
              this.axios.delete(uri);
            }
        }
    }
</script>

Here, I have written the component that displays the items in a tabular form and also, I have defined two other buttons one is for EditItem.vue and other is Delete function.


We also need to create the third and final component called EditItem.vue component.

// EditItem.vue

<template>
    <div>
        <h1>Update Item</h1>
        <div class="row">
          <div class="col-md-10"></div>
          <div class="col-md-2"><router-link :to="{ name: 'DisplayItem' }" class="btn btn-success">Return to Items</router-link></div>
        </div>

        <form v-on:submit.prevent="updateItem">
            <div class="form-group">
                <label>Item Name</label>
                <input type="text" class="form-control" v-model="item.name">
            </div>

            <div class="form-group">
                <label name="product_price">Item Price</label>
                <input type="text" class="form-control" v-model="item.price">
            </div>

            <div class="form-group">
                <button class="btn btn-primary">Update</button>
            </div>
        </form>
    </div>
</template>

<script>

    export default{
        data(){
            return{
                item:{}
            }
        },

        created: function(){
            this.getItem();
        },

        methods: {
            getItem()
            {
              let uri = `http://localhost:8000/items/${this.$route.params.id}/edit`;
                this.axios.get(uri).then((response) => {
                    this.item = response.data;
                });
            },

            updateItem()
            {
              let uri = 'http://localhost:8000/items/'+this.$route.params.id;
                this.axios.patch(uri, this.item).then((response) => {
                  this.$router.push({name: 'DisplayItem'});
                });
            }
        }
    }
</script>

Here, I have defined Update function with its POST request.

Now the last step is to include all this component into the app.js file.

We can remove now Example.vue component, as we do not need anymore.

// app.js

import Vue from 'vue';

import VueRouter from 'vue-router';
Vue.use(VueRouter);

import VueAxios from 'vue-axios';
import axios from 'axios';
Vue.use(VueAxios, axios);

import App from './App.vue';
import CreateItem from './components/CreateItem.vue';
import DisplayItem from './components/DisplayItem.vue';
import EditItem from './components/EditItem.vue';

const routes = [
  {
    name: 'CreateItem',
    path: '/items/create',
    component: CreateItem
  },
  {
        name: 'DisplayItem',
        path: '/',
        component: DisplayItem
  },
  {
      name: 'EditItem',
      path: '/edit/:id',
      component: EditItem
   }
];

const router = new VueRouter({ mode: 'history', routes: routes});
new Vue(Vue.util.extend({ router }, App)).$mount('#app');

Finally, go to the http://localhost:8000

VueJS and Laravel Tutorials

If you have any data then the home screen will look like this. If you click on Create Item button.

Laravel and VueJS CRUD

If you will click on Edit button, then this will your page.

Laravel 5.4 and VueJS 2.0 Tutorials

Download Project On Github

Steps

  1. Clone the repo.
  2. Run this command: composer update.
  3. Then, run this command to install npm dependencies: npm install
  4. Create a .env file and config the database.
  5. Run this command: php artisan migrate
  6. Then run this command: npm run dev
  7. Next type this command: php artisan serve. It will start the server at this URL: http://localhost:8000

Finally, our Laravel 5 VueJS Tutorial is over.

If you have any doubt in Laravel 5.4 Vuejs Tutorial then ask in a comment below, I am happy to help you out.

17 Comments
  1. Nicole Beharie says

    nice one, thanks

  2. Michael E McGuire says

    Thanks, handy all-in-one-place guide. It’d make a nice info-graphic.

  3. Mohammad Rizky Prawira says

    Great tutorial dude, I learn a lot from you.

    One suggestion though, for the delete method, you should do loop with index.
    If you splice the id, it can be different value between the item index position and the id value, because the id is auto incremented. The splice method doesnt find the start parameter if the id is larger so the items data isn’t updated.

    the directive:

    the button:
    Delete

    the function:
    let uri = `http://localhost/items/${id}`;
    this.items.splice(index,1);
    this.axios.delete(uri);

  4. Pooria says

    I have a problem now. As you said, web.php contains ‘resource’ route for ‘items’ and Vue is using ‘items’ too.

    So when you are clicking the links and travel through javascript, everything is ok, but when you press F5 on your keyboard or try to access localhost:8000/edit/1, the web.php file comes in and says there is no route for ‘edit’!

    1. Krunal says

      It is single page application, you do not need to refresh the page because if you do, it will take a web.php file.

  5. Femi says

    A very great and super cool tutorial.
    Thanks for putting this together.

    I think you make the call to fetchItems ( i.e this.fetchItems(); )when any item is deleted, with this, the view is refreshed without having to refresh the page.

    deleteItem(id)
    {
    let uri = `http://127.0.0.1:9900/items/${id}`;
    this.items.splice(id, 1);
    this.axios.delete(uri);
    this.fetchItems();
    }

  6. Ming says

    Hello! thanks for this tutorial!

    But i have an issue with the delete button

    DELETE http://localhost:8000/items/1 500 (Internal Server Error)

    Uncaught (in promise) Error: Request failed with status code 500

  7. Femi says

    I think you we can also make the call to fetchItems ( i.e this.fetchItems(); ) when any item is deleted, with that the view data is refreshed without having to refresh the whole page.

    deleteItem(id)
    {
    let uri = `http://127.0.0.1:9900/items/${id}`;
    this.items.splice(id, 1);
    this.axios.delete(uri);
    this.fetchItems();
    }

    In all, a very great tutorial.

  8. Femi says

    I think we can also make the call to fetchItems ( i.e this.fetchItems(); ) when any item is deleted, with that the view data is refreshed without having to refresh the whole page.

    deleteItem(id)
    {
    let uri = `http://127.0.0.1:9900/items/${id}`;
    this.items.splice(id, 1);
    this.axios.delete(uri);
    this.fetchItems();
    }

    In all, a very great tutorial.

    1. Jun Tabudlong says

      This can be accomplished by adding/modifying the elements with an Index inside DisplayItem component:
      1. Adding an Index to v-for and v-on:click

      Delete
      2. And in the deleteItem method
      deleteItem(index, id)
      {
      let uri = `/items/${id}`;
      this.items.splice(index, 1);
      this.axios.delete(uri);
      }

  9. Alugbin Abiodun says

    Please if i want to use say summernote, where will i put the libraries???

    1. Krunal says

      If it is downloadable via npm then it will be in the node_modules folder.

  10. Hitendra says

    How can i pass data from one component to other component?

    1. Krunal says

      Use the Vuex library for state management in Vuejs.

  11. GMananquil says

    well done

  12. Flavio Ferreira says
  13. Ray says

    Since it is a single page app, how can I modify the route in other to allow another pages (for instance add data on users …)

Leave A Reply

Your email address will not be published.