Laravel 11 Vue 3 CRUD App Tutorial Example will show you how to build a simple CRUD (Create, Read, Update, Delete) application using Laravel 11 and Vue 3. We’ll use Vue Router 4 for routing and utilize Vite for streamlined configuration.
Laravel 11 + Vue 3 CRUD Example Tutorial
Follow step by steps to implement Laravel 11 vue js 3 crud from scratch.
- Install Laravel latest App
- Configure Database Details
- Generate Model and Migration
- Create Controller
- Configure Routes for Laravel Vue js Crud
- Install npm Packages for Laravel Vuejs CRUD
- Initiate Vue in Laravel
- Create Vuejs CRUD Components
- Create Vue Routes for Laravel Vue CRUD
- Include Dependencies to app.js
- Run Development Server
#1 Download Laravel App
Before proceeding with the installation of Laravel 11, ensure that your system meets the following prerequisites:
- Laravel 11 requires PHP version 8.2 or higher. You can verify your PHP version by running php -v in your terminal or command prompt. If you don’t have PHP 8.2 installed, you’ll need to upgrade your PHP version.
- Laravel supports multiple database systems such as MySQL, PostgreSQL, SQLite, and SQL Server. In Laravel 11, they have predefined DB_CONNECTION=sqlite in the .env file, but if you are using MySQL, you will need to update it.
To install Laravel 11, run the following command in your terminal:
composer create-project laravel/laravel:^11.0 laravel-vue-crud
If you prefer to install Laravel based on your PHP version, use the following command:
composer create-project laravel/laravel laravel-vue-crud
Once the installation is complete, navigate to the project directory:
laravel-vue-crud
#2 Configure Database Credentials
Afterward, include your database credentials in the .env file situated within your project’s root directory.
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=#db_name
DB_USERNAME=#db_username
DB_PASSWORD=#db_password
#3 Generate Model and Migration
In the next step, you need to create a model and migration file in Laravel app. For generating the Model and Migration file your just need to run the following command.
php artisan make:model Product -m
After that navigate database\migrations and open the database\migrations\2023_04_06_061025_create_products_table.php file and update the below code on it.
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->string('sku');
$table->string('amount');
$table->text('description')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('products');
}
};
Now, run the migrate command to generate the table in the database.
php artisan migrate
Now open your model app\Models\Product.php and add the fallible properties same as below.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
use HasFactory;
protected $fillable = ['title', 'sku', 'amount', 'description'];
}
#4 Create Controller
Now, you will need to create a controller to manage Laravel Vue.js CRUD operations. Execute the following command, and it will generate a controller file within your application.
php artisan make:controller Api/ProductController
Now, open app/Http/Controllers/Api/ProductController.php file and put the below code on it.
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Product;
class ProductController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
$products = Product::orderby('id', 'desc')->get();
return response()->json($products);
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
$product = Product::create($request->all());
return response()->json([
'status' => 'success',
'product' => $product
]);
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
$product = Product::find($id);
$product->update($request->all());
return response()->json([
'status' => 'success',
'product' => $product
]);
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
$product = Product::find($id);
$product->delete();
return response()->json('Product successfully deleted!');
}
}
#5 Configure Routes for Laravel Vue js Crud
Open the routes/web.php file and append the following routes to it. When incorporating API routes, ensure to update the web routes accordingly to resemble something like this.
<?php
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider and all of them will
| be assigned to the "web" middleware group. Make something great!
|
*/
Route::get('{any}', function () {
return view('app');
})->where('any', '.*');
Now, open the routes/api.php file and update Laravel Vue js CRUD example.
<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\Api\ProductController;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider and all of them will
| be assigned to the "api" middleware group. Make something great!
|
*/
Route::middleware('api')->group(function () {
Route::resource('products', ProductController::class);
});
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
return $request->user();
});
#6 Install npm Pacakges for Laravel Vuejs CRUD
Hurrah! Backend work is completed now you need to install npm packages to create vue.js crud in Laravel app.
First, you need to generate Laravel ui package, it will manifest vue Laravel scaffold.
composer require laravel/ui
php artisan ui vue
Now install the npm package and then run the dev command it will reinitialize the components.
npm install && npm run dev
Next, install the vue axios using the below command.
npm install vue-axios
In Vue 2 to install Vue Router you can use npm install vue-router but we are using vue3 and latest router version is 4. So we will go this command.
npm i vue-router@next
If you prefer to utilize Bootstrap, you can install the Bootstrap package by executing the following command:
npm install bootstrap
#7 Initiate Vue in Laravel
Now we will see how to connect blade files with vue resources js.
For this, you need to create an app.blade.php inside the resources/views directory. So, open the resources/views/app.blade.php file and update the below code on it.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>How To Install Vue 3 in Laravel with Vite</title>
@vite('resources/css/app.css')
</head>
<body>
<div id="app"></div>
@vite('resources/js/app.js')
</body>
</html>
#8 Create Vuejs CRUD Components
Next, you need to add App.vue inside the resources js directory which will show menus and initiate the router view.
So, create the App.vue file in resources/js folder and open the resources/js/App.vue file and put the below code.
<template>
<div class="container">
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="collapse navbar-collapse">
<div class="navbar-nav">
<router-link to="/" class="nav-item nav-link">Home</router-link>
<router-link :to="{ name: 'ProductIndex' }" class="nav-item nav-link">Products</router-link>
</div>
</div>
</nav>
<router-view> </router-view>
</div>
</template>
<script>
export default {}
</script>
Now you need to create a “products” folder inside the resources/js/components directory.
After this create three components inside the products directory.
- Index.vue
- Create.vue
- Edit.vue
First, open resources/js/components/products/Index.vue file and put the below code on it.
<template>
<div class="container">
<h2 class="text-center">Products List</h2>
<div class="row">
<div class="col-md-12">
<router-link :to="{ name: 'ProductCreate' }" class="btn btn-primary btn-sm float-right mb-2">Add Product</router-link>
</div>
</div>
<div class="row">
<div class="col-md-12">
<table class="table">
<thead>
<tr>
<th>#</th>
<th>Title</th>
<th>SKU</th>
<th>Amount</th>
<th>Description</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr v-for="(product, key) of products">
<td>{{ key+1 }}</td>
<td>{{ product.title }}</td>
<td>{{ product.sku }}</td>
<td>{{ product.amount }}</td>
<td>{{ product.description }}</td>
<td>
<router-link class="btn btn-success btn-sm" :to="{ name: 'ProductEdit', params: { productId: product.id }}">Edit</router-link>
<button class="btn btn-danger btn-sm ml-2" @click="deleteProduct(product.id)">Delete</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
products: {}
}
},
created() {
this.getProducts();
},
methods: {
getProducts() {
this.axios.get('/api/products').then(response => {
this.products = response.data;
}).catch(error=>{
console.log(error)
})
},
deleteProduct(productId) {
this.axios
.delete(`/api/products/${productId}`)
.then(response => {
let i = this.products.map(data => data.id).indexOf(productId);
this.products.splice(i, 1)
});
}
}
}
</script>
Next, open the resources/js/components/products/Create.vue file and place the code on it.
<template>
<div class="container">
<h2 class="text-center">Create product</h2>
<div class="row">
<div class="col-md-12">
<router-link :to="{ name: 'ProductIndex' }" 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="product.title">
</div>
<div class="form-group">
<label>SKU</label>
<input type="text" class="form-control" v-model="product.sku">
</div>
<div class="form-group">
<label>Amount</label>
<input type="number" class="form-control" v-model="product.amount">
</div>
<div class="form-group">
<label>Description</label>
<textarea type="text" rows="5" class="form-control" v-model="product.description"></textarea>
</div>
<button type="button" class="btn btn-primary" @click="createProduct()">Create</button>
</form>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
product: {}
}
},
methods: {
createProduct() {
this.axios.post('/api/products', this.product)
.then(response => {
this.$router.push({ name: 'ProductIndex' })
})
.catch(error=>{
console.log(error)
})
}
}
}
</script>
Again open the resources/js/components/products/Edit.vue file and put the below code on it.
<template>
<div class="container">
<h2 class="text-center">Update Product</h2>
<div class="row">
<div class="col-md-12">
<router-link :to="{ name: 'ProductIndex' }" 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="product.title">
</div>
<div class="form-group">
<label>SKU</label>
<input type="text" class="form-control" v-model="product.sku">
</div>
<div class="form-group">
<label>Amount</label>
<input type="number" class="form-control" v-model="product.amount">
</div>
<div class="form-group">
<label>Description</label>
<textarea type="text" rows="5" class="form-control" v-model="product.description"></textarea>
</div>
<button type="button" class="btn btn-primary" @click="updateProduct()"> Update </button>
</form>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
product: {}
}
},
mounted() {
this.editProduct(this.$route.params.productId);
},
methods: {
editProduct(productId) {
this.axios.get(`/api/products/${productId}`)
.then((response) => {
this.product = response.data;
});
},
updateProduct() {
this.axios
.patch(`/api/products/${this.$route.params.productId}`, this.product)
.then((response) => {
this.$router.push({ name: 'ProductIndex' });
});
}
}
}
</script>
To create a home view, you’ll need to generate a Home.vue file inside the resources/js/components folder. Then, open the resources/js/components/Home.vue file and update it with the following code:
<template>
<div>
<h1>This is the home page.</h1>
</div>
</template>
#9 Create Vue Routes for Laravel Vue CRUD
Now we create new file “routes.js” inside “resources/js” directory. Next, open the resources/js/routes.js file and place the below code on it.
import { createWebHistory, createRouter } from "vue-router";
import Home from "@/components/Home.vue";
import ProductIndex from "@/components/products/Index.vue";
import ProductCreate from './components/products/Create.vue';
import ProductEdit from './components/products/Edit.vue';
const routes = [
{
path: "/",
name: "Home",
component: Home,
},
{
path: "/products",
name: "ProductIndex",
component: ProductIndex,
},
{
path: '/products/create',
name: "ProductCreate",
component: ProductCreate,
},
{
path: '/products/edit/:productId',
name: "ProductEdit",
component: ProductEdit,
}
];
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;
#10 Include Dependencies to app.js
In the last step of Laravel Vue.js CRUD Example, we will update our npm packages, routes and render the app in the main app.js file.
So, open the resources\js\app.js file and update your packages like this.
import "bootstrap/dist/css/bootstrap.min.css"
import { createApp } from 'vue';
import App from './App.vue';
import axios from 'axios'
import VueAxios from 'vue-axios'
import router from './routes'
createApp(App).use(router).use(VueAxios, axios).mount('#app');
#11 Run Development Server
After completing all the prerequisites for the Laravel Vue.js CRUD application, proceed by running the commands npm run dev and php artisan serve. In earlier versions of Laravel, the command was npm run watch, but with the introduction of Vite, it has been changed to dev.
The dev command initializes our js components and the serve command run our application.
npm run dev
php artisan serve
Now, hit the below ur and enjoy.
http://localhost:8000/
or
http://127.0.0.1:8000/
This example is compatible with Laravel 9, Laravel 10, and Laravel 11 along with Vue 3 and Vite for seamless integration and optimal performance.