Laravel + Vue JS CRUD Single Page Applicationの作成

今回は、LaravelとVue JSを使ったSingle Page Applicationの作成方法についてご案内します。

ここでは、セットアップに必要な手順を説明します。

このコマンドでLaravelのプロジェクトを新規に作成する必要があります。

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

次に、プロジェクトの.env configファイルにデータベース名、ユーザー名、パスワードを追加して、データベース接続を行う必要があります。

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

LaravelでArticleモデルを作成するには、以下のコマンドを実行してください。

php artisan make:model Article -m

database/migrations/create_articles_table.php に以下のコードを追加してください。

<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateArticlesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('artcles', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->text('descriptions');            
            $table->timestamps();
        });
    }
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('articles');
    }
}

マイグレーションを呼び出すには、以下のコマンドを実行してください。

php artisan migrate

記事コントローラを作成

記事コントローラを作成し、CRUD操作のメソッドを定義する必要があります

php artisan make:controller ArticleController

Article Controllerを以下のコードで更新します。

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Article;
class ArticleController extends Controller
{
    public function index()
    {
        $articles = Article::all()->toArray();
        return array_reverse($articles);      
    }
    public function store(Request $request)
    {
        $article = new Article();
        $article->title = $request->input('title');
        $article->description = $request->input('description');
        $article->save();

        return response()->json('New Article is successfully created!');
    }
    public function show($id)
    {
        $article = Article::find($id);
        return response()->json($article);
    }
    public function update($id, Request $request)
    {
        $article = Article::find($id);
        $article->title= $request->title;
        $article->description = $request->description;
        $article->save();

        return response()->json('Article is successfully updated!');
    }
    public function destroy($id)
    {
        $article = Article::find($id);
        $article->delete();
        return response()->json('Article is successfully deleted!');
    }
}

routesのweb.phpとapi.phpを更新してください。

routes/web.php

<?php
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
*/
 
Route::get('{any}', function () {
    return view('app');
})->where('any', '.*');

routes/api.php

<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ArticleController;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
*/
Route::middleware('api')->group(function () {
    Route::resource('articles', ArticleController::class);
});

laravel/ui composer パッケージをインストールします。

composer require laravel/ui

次に、Vueの足場を設定します。

laravel/uiパッケージには、Vueを使い始めるために必要なすべてのものを自動的に足場にしてくれる便利なArtisanコマンドがいくつか用意されています。

php artisan ui vue

ファイルをコンパイルする

最後に、新しく追加された依存関係をインストールして、コンパイルする必要があります。

npm install && npm run dev

コマンドを使用して、vue router および vue axios パッケージをインストールします。

npm install vue-router vue-axios

次に、npm パッケージをインストールし、アセットをコンパイルするために、次のコマンドを実行します。

npm install
npm run watch

LaravelでVueを開始する

layoutフォルダを作成し、このフォルダ内にapp.blade.phpを作成してアプリケーションを設定する必要があります。

resources/views/layout/app.blade.php

<!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>Vue JS CRUD Operations in Laravel</title>
    <link href="{{ mix('css/app.css') }}" type="text/css" rel="stylesheet" />
</head>
<body>
    <div id="app"></div>
    <script src="{{ mix('js/app.js') }}" type="text/javascript"></script>
</body>
</html>

App.vue ファイルに router-view 命令を追加する必要があります。そこで、resources/js フォルダに App.js ファイルを作成します。

resources/js/App.js

<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">Articles List</router-link>
                    <router-link to="/create" class="nav-item nav-link">Create Article</router-link>
                </div>
            </div>
        </nav>
        <router-view> </router-view>
    </div>
</template>
 
<script>
    export default {}
</script>

そして、resources/js/componentsフォルダの中に必要なvue jsコンポーネントファイルを作成します。

resources/js/components/AllArticle.vue

<template>
    <div>
        <h2 class="text-center">Article List</h2>
 
        <table class="table">
            <thead>
            <tr>
                <th>ID</th>
                <th>Title</th>
                <th>Desciption</th>
                <!-- <th>Actions</th> -->
            </tr>
            </thead>
            <tbody>
            <tr v-for="article in articles" :key="a.article">
                <td>{{ article.id }}</td>
                <td>{{ article.title }}</td>
                <td>{{ article.description}}</td>
                <td>
                    <div class="btn-group" role="group">
                        <router-link :to="{name: 'edit', params: { id: article.id }}" class="btn btn-success">Edit</router-link>
                        <button class="btn btn-danger" @click="deleteArticle(article.id)">Delete</button>
                    </div>
                </td>
            </tr>
            </tbody>
        </table>
    </div>
</template>
 
<script>
    export default {
        data() {
            return {
                articles: []
            }
        },
        created() {
            this.axios
                .get('http://localhost:8000/api/articles/')
                .then(response => {
                    this.articles = response.data;
                });
        },
        methods: {
            deleteArticle(id) { 
                this.axios
                    .delete(`http://localhost:8000/api/articles/${id}`)
                    .then(response => {
                        let i = this.articles.map(data => data.id).indexOf(id);
                        this.articles.splice(i, 1)
                    });
            }
        }
    }
</script>

resources/js/components/CreateArticle.vue

<template>
    <div>
        <h3 class="text-center">Create Article</h3>
        <div class="row">
            <div class="col-md-6">
                <form @submit.prevent="addArticle">
                    <div class="form-group">
                        <label>Title</label>
                        <input type="text" class="form-control" v-model="article.title">
                    </div>
                    <div class="form-group">
                        <label>Description</label>
                        <input type="text" class="form-control" v-model="article.description">
                    </div>
                    <button type="submit" class="btn btn-primary">Create</button>
                </form>
            </div>
        </div>
    </div>
</template>
 
<script>
    export default {
        data() {
            return {
                article: {}
            }
        },
        methods: {
            addArticle() {
                this.axios
                    .post('http://localhost:8000/api/articles', this.article)
                    .then(response => (
                        this.$router.push({ name: 'home' })
                    ))
                    .catch(err => console.log(err))
                    .finally(() => this.loading = false)
            }
        }
    }
</script>

 resources/js/components/EditArticle.vue

<template>
    <div>
        <h3 class="text-center">Edit Article</h3>
        <div class="row">
            <div class="col-md-6">
                <form @submit.prevent="updateArticle">
                    <div class="form-group">
                        <label>Title</label>
                        <input type="text" class="form-control" v-model="article.title">
                    </div>
                    <div class="form-group">
                        <label>Detail</label>
                        <input type="text" class="form-control" v-model="article.description">
                    </div>
                    <button type="submit" class="btn btn-primary">Update</button>
                </form>
            </div>
        </div>
    </div>
</template>
 
<script>
    export default {
        data() {
            return {
                article: {}
            }
        },
        created() {
            this.axios
                .get(`http://localhost:8000/api/articles/${this.$route.params.id}`)
                .then((res) => {
                    this.article = res.data;
                });
        },
        methods: {
            updateArticle() {
                this.axios
                    .patch(`http://localhost:8000/api/articles/${this.$route.params.id}`, this.article)
                    .then((res) => {
                        this.$router.push({ name: 'home' });
                    });
            }
        }
    }
</script>

vueのルートを作成するには、resources/jsディレクトリの中にroutes.jsを作成します。

resources/js/routes.js

import AllArticle from './components/AllArticle.vue';
import CreateArticle from './components/CreateArticle.vue';
import EditArticle from './components/EditArticle.vue';
 
export const routes = [
    {
        name: 'home',
        path: '/',
        component: AllArticle
    },
    {
        name: 'create',
        path: '/create',
        component: CreateArticle
    },
    {
        name: 'edit',
        path: '/edit/:id',
        component: EditArticle
    }
];

最後にVue App.jsを定義します。

 resources/js/app.js

/**
 * 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 App from './App.vue';
import VueAxios from 'vue-axios';
import VueRouter from 'vue-router';
import axios from 'axios';
import { routes } from './routes';
/**
 * 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.
 */
Vue.use(VueRouter);
Vue.use(VueAxios, axios);
 
const router = new VueRouter({
    mode: 'history',
    routes: routes
});
 
const app = new Vue({
    el: '#app',
    router: router,
    render: h => h(App),
});

アプリを起動するには、以下の2つのコマンドを実行します。

npm run watch
php artisan serve

ブラウザで http://127.0.0.1:8000 にアクセスすると、記事の一覧表示、記事の作成、更新ができます。

この記事があなたのお役に立てれば幸いです。

By Tsuki



アプリ関連ニュース

お問い合わせはこちら

お問い合わせ・ご相談はお電話、またはお問い合わせフォームよりお受け付けいたしております。

tel. 06-6454-8833(平日 10:00~17:00)

お問い合わせフォーム