Build Mini App CRUD With Laravel And Vuejs

Lượt xem: 6000

CRUD (Create, Read, Update, and Delete) là các thao tác dữ liệu cơ bản và là một trong những điều đầu tiên bạn học với tư cách là nhà phát triển Laravel.

Trong ví dụ này Laravel Vuejs CRUD, Chúng ta sẽ tìm hiểu cách triển khai Laravel Vuejs CRUD (create, read, update, and delete) spa (Single Page Application) với Vue.js , Vue Router và Laravel Framework.

Ngày nay, các framework JS phổ biến nhất là Angular JS và Vue JS. Angular JS và Vue JS là những framework JS rất thân thiện với người dùng và phổ biến nhất. Nó cung cấp khả năng quản lý toàn bộ dự án hoặc ứng dụng mà không cần làm mới trang và xác thực jquery mạnh mẽ.

Ví dụ về ứng dụng CRUD của Laravel Vue JS (SPA):
1.Cài đặt dự án Laravel
2. Định cấu hình chi tiết cơ sở dữ liệu
3.Cài đặt phụ thuộc NPM
4.Tạo di chuyển (migrate), mô hình (model) và bộ điều khiển (controller)
5. Xác định tuyến đường (route) trong web.php
6.Tạo ứng dụng Vue
7.Tạo thành phần (components) cho ứng dụng Vue
8.Xác định tuyến đường (routes) cho ứng dụng Crud trong bộ định tuyến Vue
9.Thêm các phụ thuộc Vue.js vào app.js
10.Cập nhật vite.config.js
11. Chạy máy chủ phát triển
Yêu cầu máy chủ
PHP 8.0
Laravel 9.x
MySQL

1. Cài đặt dự án Laravel (Install Laravel Project)

Đầu tiên, mở Terminal và chạy lệnh sau để tạo một dự án laravel mới:


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

hoặc, nếu bạn đã cài đặt Trình cài đặt Laravel


laravel new crud-spa


2. Định cấu hình chi tiết cơ sở dữ liệu

Sau khi cài đặt Đi tới thư mục gốc của dự án, mở tệp .env và đặt chi tiết cơ sở dữ liệu như sau:


DB_CONNECTION=mysql 
DB_HOST=127.0.0.1 
DB_PORT=3306 
DB_DATABASE=[DATABASE NAME] //larave_vuejs
DB_USERNAME=[DATABASE USERNAME] //root
DB_PASSWORD=[DATABASE PASSWORD] //

3.Cài đặt phụ thuộc NPM

Chạy lệnh sau để cài đặt các phần phụ thuộc của giao diện người dùng:


npm install

Lưu ý: Máy cần phải cài đặt Nodejs trước đó. Xem thêm cài đặt Nodejs trên windows 10

Tiếp theo, cài đặt vue , vue-router và vue-axios . Vue-axios sẽ được sử dụng để gọi API của Laravel. Chạy lệnh sau trên terminal:


npm install vue vue-router vue-axios --save

Xem thêm làm quen nhanh với laravel

4.Tạo di chuyển (migrate), mô hình (model) và bộ điều khiển (controller)

Tạo Category model (mô hình) migrate (di chuyển)  và controller (bộ điều khiển). Chạy lệnh sau cho điều đó:


php artisan make:model Category -mcr

-mcr đối số này sẽ tạo model, migrate và controller trong một lệnh đơn.

Bây giờ, hãy mở tệp migrate của cateogry (danh mục)  từ folder database/migrations và thay thế mã trong hàm up ():


public function up()
{
    Schema::create('categories', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->string('title');
        $table->text('description');
        $table->timestamps();
    });
}

 

Migrate database chúng ta sử dụng lệnh:


php artisan migrate

Bây giờ, hãy mở model Category.php từ App/Models và cập nhật mã vào model Category.php:


<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Category extends Model {

   use HasFactory;

   protected $fillable = ['title','description'];

}

?> 

Tiếp theo, mở CategoryController.php và thêm mã vào các phương thức index, store, update và delete như sau:


<?php

namespace App\Http\Controllers;

use App\Models\Category;
use Illuminate\Http\Request;

class CategoryController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $categories = Category::all(['id','title','description']);
        return response()->json($categories);
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $category = Category::create($request->post());
        return response()->json([
            'message'=>'Category Created Successfully!!',
            'category'=>$category
        ]);
    }

    /**
     * Display the specified resource.
     *
     * @param  \App\Models\Category  $category
     * @return \Illuminate\Http\Response
     */
    public function show(Category $category)
    {
        return response()->json($category);
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Models\Category  $category
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, Category $category)
    {
        $category->fill($request->post())->save();
        return response()->json([
            'message'=>'Category Updated Successfully!!',
            'category'=>$category
        ]);
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Models\Category  $category
     * @return \Illuminate\Http\Response
     */
    public function destroy(Category $category)
    {
        $category->delete();
        return response()->json([
            'message'=>'Category Deleted Successfully!!'
        ]);
    }
}

5. Xác định tuyến đường (route) trong web.php

Bây giờ hãy xác định các tuyến trong tệp tuyến web.php và api.php. Chuyển đến thư mục tuyến đường và mở tệp web.php và api.php rồi cập nhật các tuyến đường sau:

routes / api.php

Route::resource('category',App\Http\Controllers\CategoryController::class)->only(['index','store','show','update','destroy']);

routes / web.php

 


Route::get('/', function () {
    return view('app');
});

6.Tạo ứng dụng Vue

Trong bước này, hãy chuyển đến thư mục resource/views, tạo tệp app.blade.php và thêm mã sau vào app.blade.php như sau:


<!doctype html> 
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> 
   <head> 
        <meta charset="utf-8"> 
        <meta name="viewport" content="width=device-width, initial-scale=1"> 
        <meta name="csrf-token" value="{{ csrf_token() }}"/> 
        <title> Laravel Vue CRUD App - dandevblog</title> 
        <link href="https://fonts.googleapis.com/css?family=Nunito:200,600" rel="stylesheet" type="text/css"> 
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous">
        @vite(['resources/css/app.css', 'resources/js/app.js'])
    </head> 
    <body> 
        <div id="app"> 
        </div> 
       
    </body> 
</html> 

7.Tạo thành phần (components) cho ứng dụng Vue

Trong bước này, hãy chuyển đến thư mục  resource/ js, tạo thư mục components và tạo các tệp như sau:

  • App.vue
  • Welcome.vue
  • category / List.vue
  • category / Add.vue
  • category / Edit.vue
App.vue là tệp chính của ứng dụng Vue của chúng ta. Chúng ta sẽ xác định chế độ xem bộ định tuyến trong tệp đó. Tất cả các tuyến đường sẽ được hiển thị trong tệp App.vue.
 
Mở tệp Welcome.vue và Cập nhật đoạn mã sau:
 

<template>
   <div class="container mt-5">>
        <div class="col-12 text-center">
            <h1>dandevblog</h1>
            <a href="https://dandev.net" target="_blank">Visit For More Blogs</a>
        </div>
    </div>
</template>

Mở tệp App.vue và Cập nhật đoạn mã sau:


<template>
    <main>
        <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
            <div class="container-fluid">
                <router-link to="/" class="navbar-brand" href="#">Laravel Vue Crud App - dandevblog</router-link>
                <div class="collapse navbar-collapse">
                    <div class="navbar-nav">
                        <router-link exact-active-class="active" to="/" class="nav-item nav-link">Home</router-link>
                        <router-link exact-active-class="active" to="/category" class="nav-item nav-link">Category</router-link>
                    </div>
                </div>
            </div>
        </nav>
        <div class="container mt-5">
            <router-view></router-view>
        </div>
    </main>
</template>
 
<script>
    export default {}
</script>

Tiếp theo, mở file List.vue trong thư mục components/category/List.vue và thêm mã sau:


<template> 
    <div class="row"> 
        <div class="col-12 mb-2 text-end"> 
            <router-link :to='{name:"categoryAdd"}' class="btn btn-primary"> Create</router-link> 
        </div> 
        <div class="col-12"> 
            <div class="card"> 
                <div class="card-header"> 
                    <h4> Category</h4> 
                </div> 
                <div class="card-body"> 
                    <div class="table-responsive"> 
                        <table class="table table-bordered"> 
                            <thead> 
                                <tr> 
                                    <th> ID</th> 
                                    <th> Title</th> 
                                    <th> Description</th> 
                                    <th> Actions</th> 
                                </tr> 
                            </thead> 
                            <tbody v-if="categories.length > 0"> 
                                <tr v-for="(category,key) in categories" :key="key"> 
                                    <td> {{ category.id }}</td> 
                                    <td> {{ category.title }}</td> 
                                    <td> {{ category.description }}</td> 
                                    <td> 
                                        <router-link :to='{name:"categoryEdit",params:{id:category.id}}' class="btn btn-success"> Edit</router-link> 
                                        <button type="button" @click="deleteCategory(category.id)" class="btn btn-danger"> Delete</button> 
                                    </td> 
                                </tr> 
                            </tbody> 
                            <tbody v-else> 
                                <tr> 
                                    <td colspan="4" align="center"> No Categories Found.</td> 
                                </tr> 
                            </tbody> 
                        </table> 
                    </div> 
                </div> 
            </div> 
        </div> 
    </div> 
</template> 

<script> 
export default {
    name:"categories",
    data(){
        return {
            categories:[]
        }
    },
    mounted(){
        this.getCategories()
    },
    methods:{
        async getCategories(){
            await this.axios.get('/api/category').then(response=>{
                this.categories = response.data
            }).catch(error=>{
                console.log(error)
                this.categories = []
            })
        },
        deleteCategory(id){
            if(confirm("Are you sure to delete this category ?")){
                this.axios.delete(`/api/category/${id}`).then(response=>{
                    this.getCategories()
                }).catch(error=>{
                    console.log(error)
                })
            }
        }
    }
}
</script> 

Tiếp theo, mở resources /js / components/ category / Add.vue và cập nhật mã sau:


<template> 
    <div class="row"> 
        <div class="col-12"> 
            <div class="card"> 
                <div class="card-header"> 
                    <h4> Add Category</h4> 
                </div> 
                <div class="card-body"> 
                    <form @submit.prevent="create"> 
                        <div class="row"> 
                            <div class="col-12 mb-2"> 
                                <div class="form-group"> 
                                    <label> Title</label> 
                                    <input type="text" class="form-control" v-model="category.title"> 
                                </div> 
                            </div> 
                            <div class="col-12 mb-2"> 
                                <div class="form-group"> 
                                    <label> Description</label> 
                                    <input type="text" class="form-control" v-model="category.description"> 
                                </div> 
                            </div> 
                            <div class="col-12"> 
                                <button type="submit" class="btn btn-primary"> Save</button> 
                            </div> 
                        </div>                         
                    </form> 
                </div> 
            </div> 
        </div> 
    </div> 
</template> 

<script> 
export default {
    name:"add-category",
    data(){
        return {
            category:{
                title:"",
                description:""
            }
        }
    },
    methods:{
        async create(){
            debugger
            await this.axios.post('/api/category',this.category).then(response=>{
                this.$router.push({name:"categoryList"})
            }).catch(error=>{
                console.log(error)
            })
        }
    }
}
</script>  

Tiếp theo, mở resources/js/components/category/Edit.vue và cập nhật mã sau:


<template>
    <div class="row">
        <div class="col-12">
            <div class="card">
                <div class="card-header">
                    <h4>Update Category</h4>
                </div>
                <div class="card-body">
                    <form @submit.prevent="update">
                        <div class="row">
                            <div class="col-12 mb-2">
                                <div class="form-group">
                                    <label>Title</label>
                                    <input type="text" class="form-control" v-model="category.title">
                                </div>
                            </div>
                            <div class="col-12 mb-2">
                                <div class="form-group">
                                    <label>Description</label>
                                    <input type="text" class="form-control" v-model="category.description">
                                </div>
                            </div>
                            <div class="col-12">
                                <button type="submit" class="btn btn-primary">Update</button>
                            </div>
                        </div>                        
                    </form>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
export default {
    name:"update-category",
    data(){
        return {
            category:{
                title:"",
                description:"",
                _method:"patch"
            }
        }
    },
    mounted(){
        this.showCategory()
    },
    methods:{
        async showCategory(){
            await this.axios.get(`/api/category/${this.$route.params.id}`).then(response=>{
                const { title, description } = response.data
                this.category.title = title
                this.category.description = description
            }).catch(error=>{
                console.log(error)
            })
        },
        async update(){
            await this.axios.post(`/api/category/${this.$route.params.id}`,this.category).then(response=>{
                this.$router.push({name:"categoryList"})
            }).catch(error=>{
                console.log(error)
            })
        }
    }
}
</script>

8.Xác định tuyến đường (routes) cho ứng dụng Crud trong bộ định tuyến Vue

Bây giờ, bạn cần xác định router Vue, vì vậy hãy chuyển đến thư mục resources/js, tạo tệp routes.js và cập nhật mã sau:


import Welcome from './components/Welcome.vue'
import CategoryList from './components/category/List.vue'
import CategoryCreate from './components/category/Add.vue'
import CategoryEdit from './components/category/Edit.vue'

export const routes = [
    {
        name: 'home',
        path: '/',
        component: Welcome
    },
    {
        name: 'categoryList',
        path: '/category',
        component: CategoryList
    },
    {
        name: 'categoryEdit',
        path: '/category/:id/edit',
        component: CategoryEdit
    },
    {
        name: 'categoryAdd',
        path: '/category/add',
        component: CategoryCreate
    }
]

9.Thêm các phụ thuộc Vue.js vào app.js

Bây giờ, bạn cần thêm tất cả các routes, vue-axios và các phần phụ thuộc khác.

resources/ js / app.js


import './bootstrap';
import { createApp } from 'vue'

import App from './components/App.vue';
import * as VueRouter from 'vue-router';
import VueAxios from 'vue-axios';
import axios from 'axios';
import {routes} from './routes'; 

const router = VueRouter.createRouter({
    history: VueRouter.createWebHashHistory(),
    routes,
})
const app = createApp(App)
.use(router)
.use(VueAxios, axios)
.mount('#app')

 

10.Cập nhật vite.config.js


import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '@vitejs/plugin-vue'

export default defineConfig({
    plugins: [      
        laravel({
            input: ['resources/css/app.css', 'resources/js/app.js'],
            refresh: true,
        }),
        vue({
            template: {
                transformAssetUrls: {
                    // The Vue plugin will re-write asset URLs, when referenced
                    // in Single File Components, to point to the Laravel web
                    // server. Setting this to `null` allows the Laravel plugin
                    // to instead re-write asset URLs to point to the Vite
                    // server instead.
                    base: null,
 
                    // The Vue plugin will parse absolute URLs and treat them
                    // as absolute paths to files on disk. Setting this to
                    // `false` will leave absolute URLs un-touched so they can
                    // reference assets in the public directory as expected.
                    includeAbsolute: false,
                },
            },
        }),
    ],
});

Thêm vitejs/plugin-vue


npm install --save-dev @vitejs/plugin-vue

11. Chạy máy chủ phát triển


npm run dev

 

Lưu ý: ở đây mình dùng xampp làm server chạy laravel chứ không dùng php artisan (bạn có thể dùng php artisan để chạy laravel). Xem them cấu hình domain bất kỳ chạy trong mạng lan với xampp

Video thao tác cùng dandev