🐙

Laravel × Vue.js - 本の管理(CRUD 処理)ができる SPA(Single Page App) の開発方法

2022/04/16に公開

Laravel と Vue.js を使ってシンプルな Single Page Application を作成する方法について解説します。

本の管理をするための CURD 処理についてまとめました。データベースには SQLite を利用しています。

完成形のイメージはこちらです。

ソースコードはGitHubで公開しています。
https://github.com/t-aono/book-list

バックエンドの実装

Laravelインストール

プロジェクト作成。Laravel のバージョンは8を使用。

composer create-project laravel/laravel book-list --prefer-dist

php artisan --version
Laravel Framework 8.55.0

データーベースの準備

  • .envDB_CONNECTION=sqlite に変更
  • database/database.sqlite という名前で空ファイルを作成

モデルとマイグレーションファイル生成。

php artisan make:model Book -m

マイグレーションファイルを編集してカラムの追加。

Schema::create('books', function (Blueprint $table) {
    $table->id();
    $table->string('title');
    $table->string('author');
    $table->timestamps();
});

データの書き換えができるようにモデルに $fillable を指定。

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

テーブル作成。

php artisan migrate

API用コントローラーを作成

php artisan make:controller BookController --api

ルーティングの設定のため routes/api.php に以下を追加。

Route::resource('/books', App\Http\Controllers\BookController::class);

api/books/* が設定されたらOK。

php artisan route:list

GET|HEAD  | api/books             | books.index   | App\Http\Controllers\BookController@index  
POST      | api/books             | books.store   | App\Http\Controllers\BookController@store  
GET|HEAD  | api/books/create      | books.create  | App\Http\Controllers\BookController@create 
GET|HEAD  | api/books/{book}      | books.show    | App\Http\Controllers\BookController@show   
PUT|PATCH | api/books/{book}      | books.update  | App\Http\Controllers\BookController@update 
DELETE    | api/books/{book}      | books.destroy | App\Http\Controllers\BookController@destroy
GET|HEAD  | api/books/{book}/edit | books.edit    | App\Http\Controllers\BookController@edit

コントローラーに処理を追加していきます。
一覧表示、登録、更新、削除のメソッドをそれぞれ追加。

use \App\Models\Book;

    public function index()
    {
        return Book::all();
    }

    public function store(Request $request)
    {
        Book::create($request->all());
    }

    public function update(Request $request, $id)
    {
        Book::where('id', $id)->updata([
            'title' => $request->title,
            'author' => $request->author
        ]);
    }
    public function destroy($id)
    {
        Book::where('id', $id)->delete();
    }

バリデーション用にリクエストクラスを作成。

php artisan make:request StoreBook

app\Http\Requests\StoreBook.php ができるのでルールを設定。

public function authorize()
{
    return true;   ← 認証機能を使わない場合は true にしておく
}

public function rules()
{
  return [
      'title' => 'required|max:10',
      'author' => 'required|max:10',
  ];
}

バックエンドの動作チェック

サーバー起動してリクエスト。リクエストに応じてデータベースが更新できるはずです。

追加
curl -X POST http://localhost:8000/api/books  -d 'title=test&author=anyone'

一覧取得
curl -X GET http://localhost:8000/api/books

更新(2番目のデータ)
curl -X PUT http://localhost:8000/api/books/2  -d 'title=testUPD&author=anyoneUPD'

削除(2番目のデータ)
curl -X DELETE http://localhost:8000/api/books/2

フロントエンドの実装

Vue.jsインストール

フロントエンドパッケージを入れて Vue のスカフォールドしてインストール&ビルド。

composer require laravel/ui
php artisan ui vue
npm install 
npm run dev

ビュー設定

画面表示のためのコントローラーを作成しビューファイルを指定します。

php artisan make:controller BookManageController
public function index() {
    return view('book.index');
}

routes/web.php でルーティングを設定。

Route::get('/', function () {
    return view('book.index');
});

resources/views/book/index.blade.php を作成して app.js を読み込む。

<body>
  <div id="app">
    <book-component></book-component>
  </div>

  <script src="{{ mix('js/app.js') }}"></script>
</body>

mix はキャッシュにある古いスクリプトではなく新しいスクリプトを読み込むための仕組み。

一覧表示処理の実装

resources/js/components/BookComponent.vue を作成して一覧表示の部分を作る。

<li v-for="book in books" :key="book.id">
  {{ book.id }} / {{ book.title }} / {{ book.author }}
</li>

data() {
  return {
    books: {},
  }
},
created() {
  this.getBooks();
},
methods: {
  getBooks() {
    axios.get('/api/books').then(res => {
      this.books = res.data;
    });
  },

resources/js/app.js を編集してコンポーネントを追加。

Vue.component('book-component', require('./components/BookComponent.vue').default);

これで DB のデータが表示できる。

登録処理の実装

次に登録部分を作成。

<div>
  <p>タイトル:<input type="text" v-model="title"></p>
  <p>著者:<input type="text" v-model="author"></p>
  <button @click="addBook">追加</button>
</div>

methods: {
  addBook() {
    axios.post('/api/books/', {
      title: this.title,
      author: this.author
    }).then(() => {
      this.title = '',
      this.author = ''
      books = this.getBooks();
    });
},

更新処理と削除処理を実装

更新と削除も追加。

<li v-for="book in books" :key="book.id">
	{{ book.id }} / {{ book.title }} / {{ book.author }}
	<button
	  :disabled="isPush"
	  @click="displayUpdate(book)"
	>編集</button>
	<button
	  :disabled="isPush" @click="deleteBook(book.id)"
	>削除</button>
</li>

data() {
  return {
    books: {},
    title:'',
    author: '',
    isPush: false,
    updateForm: false,
    updateId: '',
    updateTitle: '',
    updateAuthor: '',
  }
},

methods: {
  getBooks() {
    axios.get('/api/books').then(res => {
      this.books = res.data;
    });
  },
  displayUpdate(book) {
    this.isPush = true;
    this.updateForm = true;
    this.updateId = book.id;
    this.updateTitle = book.title;
    this.updateAuthor = book.author;
  },
  updateBook() {
    axios.put('/api/books/' + this.updateId, {
      title: this.updateTitle,
      author: this.updateAuthor
    }).then(() => {
      this.isPush = false;
      this.updateForm = false;
      this.getBooks();
    });
  },
  updateCancel() {
    this.isPush = false;
    this.updateForm = false;
  },
  deleteBook(id) {
    axios.delete('/api/books/' + id).then(() => {
      this.getBooks();
    });
  },

これで CURD 処理が完成。

まとめ

Laravel × Vue.js でのCURD処理についてサンプルコードを用いて解説しました。

API処理やリアクティブなフロントエンドの構築が簡単ですね。

Laravel, Vue.js を使っているプロジェクトは多いので実装する際の参考になれば幸いです。

参考

Laravel 6 APIとVue.jsでSPA構築 最速入門

Discussion