Simple CRUD App with Laravel & Vue Js Step by Step

This article show how to create Laravel Vue js CRUD example tutorial step by step, Crud application understand how to build Create, Read, Update, and Delete API and how to consume APIs to perform CRUD operations in Laravel Vue JS application.

Laravel is a PHP based web application framework with an eloquent, refined syntax. Developing an app with Laravel has loads of advantages; some of them are mentioned below.

Nevertheless, in this laravel vue js crud tutorial, we will help you ascertain how to integrate the laravel vue js CRUD operations in a single page application with vue js components and laravel app. Let’s create your own laravel crud application with vuejs easy way.

Laravel Vue JS CRUD Example

Let’s start creating Laravel Vue Js CRUD operation step by step full with easy and best coding part available.

Install Laravel Project

Open terminal further run below command to manifest a new laravel project, ignore this step if project is already installed: Here we are using laravel 5.8 app.

composer create-project laravel/laravel laravel-vue-crud --prefer-dist

Setup Database

This step explains how to make database connection by adding database name, username and password in .env config file of your project:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=db
DB_USERNAME=root
DB_PASSWORD=

Generate Model and Run Migration

Run the below process to respectively create the Model (database table) and migration file:

php artisan make:model Post -m

Add Following code in database\migrations\2021_06_28_023957_create_posts_table.php

<?php

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

class CreatePostsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('title')->nullable();
            $table->longText('description')->nullable();
            $table->timestamps();
        });
    }

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

Define Product table values in app/Post.php:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    protected $fillable = [
      'title', 'description'
    ];
}

Next, you need to evoke migration with below command:

php artisan migrate

Create Controller

You need to create the product controller and define the CRUD operations methods:

php artisan make:controller Api/PostController

Open and update the below code in app\Http\Controllers\Api\PostController.php:

<?php

namespace App\Http\Controllers\Api;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Post;

class PostController extends Controller
{

    public function index()
    {
        $posts = Post::orderby('id', 'desc')->get();

        return response()->json($posts);
    }

    public function store(Request $request)
    {

        $post = Post::create($request->all());

        return response()->json([
            'status' => 'success',
            'post'   => $post
        ]);
    }

    public function show($id)
    {
        $post = Post::find($id);
        return response()->json($post);
    }

    public function update(Request $request, $id)
    {
        $post = Post::find($id);
        $post->update($request->all());

        return response()->json([
            'status' => 'success',
            'post'   => $post
        ]);
    }

    public function destroy($id)
     {
         $post = Post::find($id);
         $post->delete();

         return response()->json('Post successfully deleted!');
     }
}

Create Routes

Open routes/web.php file and add below routes on it.

<?php

use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
*/
 
Route::get('{any}', function () {
    return view('app');
})->where('any', '.*');

Next, you need to open the routes/api.php file. First, import the product controller on top, then define the CRUD API routes in the route group method as given below:

<?php

use Illuminate\Http\Request;

/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/
Route::middleware('api')->group(function () {
    Route::resource('posts', 'Api\PostController');
});

Route::middleware('auth:api')->get('/user', function (Request $request) {
    return $request->user();
});

Install Vue UI for Laravel Vue Crud

First instal install npm packages running the following command

npm install

Next install vue router and vue axios packages below command.

npm install vue-router vue-axios

The npm run watch command compiles the assets, not just that with run watch command you don’t fret about re-run the compiler over and over again.

npm run watch

Initiate Vue in Laravel

Here you need to create a layoutsfolder inside the resources/views directory and then create an app.blade.php file within the layouts folder.

Place below code in resources/views/layouts/app.blade.php file:

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="https://fonts.googleapis.com/css?family=Nunito:200,600" rel="stylesheet">
    <link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
  <div id="app">
    <main class="py-4">
        @yield('content')
    </main>
  </div>
    <script src="{{ asset('js/app.js') }}"></script>
</body>
</html>

Update coce on resources/views/welcome.blade.php file just like below.

@extends('layouts.app')
@section('content')
<div class="flex-center position-ref full-height">
       <div class="content">
           <router-view> </router-view>
      </div>
</div>
@endsection

Crete Vue CRUD Components

Here we need to create app.js file in resources/js folder, put the below code in resources/js/app.js file.

/**
 * First we will load all of this project's JavaScript dependencies which
 * includes Vue and other libraries. It is a great starting point when
 * building robust, powerful web applications using Vue and Laravel.
 */

require('./bootstrap');

window.Vue = require('vue');
import axios from 'axios';
import VueAxios from 'vue-axios';

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

Vue.use(VueAxios, axios);

import PostIndex from './components/posts/index.vue';
import PostCreate from './components/posts/create.vue';
import PostEdit from './components/posts/edit.vue';

const router = new VueRouter({
  mode: 'history',
  routes: [
    {
      path: '/', component: PostIndex, name: "PostIndex"
    },
    {
      path: '/create', component: PostCreate, name: "PostCreate"
    },
    {
      path: '/edit/:id', component: PostEdit, name: "PostEdit"
    },
  ]
});

Vue.component('example-component', require('./components/ExampleComponent.vue').default);

/**
 * Next, we will create a fresh Vue application instance and attach it to
 * the page. Then, you may begin adding components to this application
 * or customize the JavaScript scaffolding to fit your unique needs.
 */

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

Create a folder posts inside components directory so we can move all posts related here. Now we need to create the three vue js component files inside the resources/js/components/posts folder.

  • index.vue
  • create.vue
  • edit.vue

Open resources/js/components/index.vue file and put below code on it.

<template>
    <div class="container">
        <h2 class="text-center">Posts List</h2>
        <div class="row">
            <div class="col-md-12">
                <router-link :to="{ name: 'PostCreate' }"  class="btn btn-primary btn-sm float-right mb-2">Add New Post</router-link>
            </div>
        </div>
        <div class="row">
            <div class="col-md-12">
                <table class="table">
                    <thead>
                    <tr>
                        <th>#</th>
                        <th>Title</th>
                        <th>Description</th>
                        <th>Actions</th>
                    </tr>
                    </thead>
                    <tbody>
                        <tr v-for="(post, key) of posts">
                            <td>{{ key+1 }}</td>
                            <td>{{ post.title }}</td>
                            <td>{{ post.description }}</td>
                            <td>
                                <router-link class="btn btn-success btn-sm" :to="{ name: 'PostEdit', params: { postId: post.id }}">Edit</router-link>
                                <button class="btn btn-danger btn-sm" @click="deletePost(post.id)">Delete</button>
                            </td>
                            <td>
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        data() {
            return {
                posts: {}
            }
        },
        created() {
            this.getPosts();
        },
        methods: {
            getPosts() {
              this.axios.get('http://127.0.0.1:8000/api/posts')
                  .then(response => {
                      this.posts = response.data;
                  });
            },
            deletePost(postId) {
                this.axios
                    .delete(`http://127.0.0.1:8000/api/posts/${postId}`)
                    .then(response => {
                        let i = this.posts.map(data => data.id).indexOf(postId);
                        this.posts.splice(i, 1)
                    });
            }
        }
    }
</script>

This is the index file whic is show all our posts lists here.

Place code in resources/js/components/posts/create.vue file:

<template>
    <div class="container">
        <h2 class="text-center">Create Post</h2>
        <div class="row">
            <div class="col-md-12">
                <router-link :to="{ name: 'PostIndex' }" class="btn btn-primary btn-sm float-right mb-2">Back</router-link>
            </div>
        </div>
        <div class="row">
            <div class="col-md-12">
                <form>
                    <div class="form-group">
                        <label>Title</label>
                        <input type="text" class="form-control" v-model="post.title">
                    </div>
                    <div class="form-group">
                        <label>Description</label>
                        <textarea type="text" rows="5" class="form-control" v-model="post.description"></textarea>
                    </div>
                    <button type="button" class="btn btn-primary" @click="createPost()">Create</button>
                </form>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        data() {
            return {
                post: {}
            }
        },
        methods: {
            createPost() {
                this.axios.post('http://127.0.0.1:8000/api/posts', this.post)
                    .then(response => (
                        this.$router.push({ name: 'PostIndex' })
                    ))
                    .catch(err => console.log(err))
                    .finally(() => this.loading = false)
            }
        }
    }
</script>

One more open resources/js/components/posts/edit.vue template and add the below code:

<template>
    <div class="container">
        <h2 class="text-center">Update Post</h2>
        <div class="row">
            <div class="col-md-12">
                <router-link :to="{ name: 'PostIndex' }" class="btn btn-primary btn-sm float-right mb-2">Back</router-link>
            </div>
        </div>
        <div class="row">
            <div class="col-md-12">
                <form>
                    <div class="form-group">
                        <label>Title</label>
                        <input type="text" class="form-control" v-model="post.title">
                    </div>
                    <div class="form-group">
                        <label>Description</label>
                        <textarea type="text" rows="5" class="form-control" v-model="post.description"></textarea>
                    </div>
                    <button type="button" class="btn btn-primary" @click="updatePost()"> Update </button>
                </form>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        data() {
            return {
                post: {}
            }
        },
        mounted() {
            this.editPost(this.$route.params.postId);
        },
        methods: {
            editPost(postId) {
                this.axios.get(`http://127.0.0.1:8000
/api/posts/${postId}`)
                   .then((res) => {
                       this.post = res.data;
                   });
            },
            updatePost() {
                this.axios
                    .patch(`http://127.0.0.1:8000
/api/posts/${this.$route.params.postId}`, this.post)
                    .then((res) => {
                        this.$router.push({ name: 'PostIndex' });
                    });
            }
        }
    }
</script>

Run Laravel Vue CRUD App

For running the laravel vue crud app, you need to run the two following commands respectively in two different terminals simultaneously, But if you are using vertual host then you need run only npm run watch command.

npm run watch
php artisan serve

If you have virtual host open something like below, you can open your virtual host .. here we are using `http://laravel-project.co`;

http://laravel-project.co

If not use below code

http://127.0.0.1:8000/

Now Laravel Vue Crud operation is over. We hope you enjoy with this tutorial and understand how to use vue router and crud system with laravel app. Feel free to ask any question and for more update follow us on social networks.

Leave a Comment