Laravel + Vue.js開発の勉強として
Laravelチュートリアル(基本のタスクリスト)のレイアウトをVue.jsで置き換えてみた作業記録
構成
- Laravel:APIサーバー(DBのCRUD処理を提供)
- Vue.js:フロントエンド処理一式
元ネタ
-
基本のタスクリスト 5.1 Laravel
https://readouble.com/laravel/5.1/ja/quickstart.html -
Laravel 5.5 API From Scratch Using Resources
https://www.youtube.com/watch?v=4pc6cgisbKE -
Full Stack Vue.js & Laravel
https://www.youtube.com/watch?v=DJ6PD_jBtU0
バージョン
- Laravel 5.7
- Vue.js 2.5.17
完成品
Laravel API作成
API仕様
Method | URI | Action | Description |
---|---|---|---|
POST | api/task | App\Http\Controllers\TaskController@store | 新規タスク作成 |
DELETE | api/task{id} | App\Http\Controllers\TaskController@destroy | タスク削除 |
GET | api/tasks | App\Http\Controllers\TaskController@index | タスク一覧取得 |
Taskテーブルの設定
php artisan make:migration create_tasks_table --create=tasks
public function up()
{
Schema::create('tasks', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
}
マイグレーション実行
php artisan migrate
Taskモデルを作成
php artisan make:model Task
ルーティング
/**
* Display All Tasks
*/
Route::get('tasks', 'TaskController@index');
/**
* Add A New Task
*/
Route::post('task', 'TaskController@store');
/**
* Delete An Existing Task
*/
Route::delete('task/{id}', 'TaskController@destroy');
Taskコントローラー作成
php artisan make:controller TaskController --resource
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Task;
use App\Http\Resources\TaskResource;
class TaskController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
$tasks = Task::orderBy('created_at', 'asc')->get();
return TaskResource::collection($tasks);
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$task = new Task;
$task->name = $request->name;
if($task->save()) {
return new TaskResource($task);
}
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
$task = Task::findOrFail($id);
if ($task->delete()) {
return new TaskResource($task);
}
}
}
リソース作成
php artisan make:resource TaskResource
レスポンスを送り返す時に、JSONへ変換する必要のある属性の配列を返す、
toArray
メソッドをリソースクラスで定義する。
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
];
}
Taskリストページ作成
ルーティング
Route::get('/', function () {
return view('tasks');
});
View
ポイントを抜粋して解説、
ファイル全体は以下を参照
https://github.com/thanatos27/laravel-vue-quickstart/blob/master/resources/views/tasks.blade.php
CSRF保護
<!-- CSRF Protection -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<script>window.Laravel = { csrfToken: '{{ csrf_token() }}' }</script>
Vueカスタム要素呼び出し部分
<navbar></navbar>
:ナビゲーションバー
<tasks></tasks>
:タスクリスト
<div id="app">
<navbar></navbar>
<div class="container">
<tasks></tasks>
</div>
</div>
フロントエンド(Vue.js)
quickstart-basicのテンプレートファイルをベースにVue.jsでリプレース
https://github.com/laravel/quickstart-basic/blob/master/resources/views/tasks.blade.php
コンポーネント登録
Vue.component('navbar', require('./components/Navbar.vue'));
Vue.component('questionnaires', require('./components/Tasks.vue'));
ナビゲーションバー
<template>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<!-- Branding Image -->
<a class="navbar-brand" href="/">
Task List
</a>
</div>
</div>
</nav>
</template>
タスクリスト
ポイントを抜粋して解説、
ファイル全体は以下を参照
https://github.com/thanatos27/laravel-vue-quickstart/blob/master/resources/js/components/Tasks.vue
表示/非表示
Laravelの@if
をVueのv-show
構文で置き換え
<!-- Current Tasks -->
<div v-show="tasks.length">
<div class="panel panel-default">
<div class="panel-heading">
Current Tasks
</div>
繰り返し制御
Laravelの@foreach
をVueのv-for
構文で置き換え
<tr v-for="task in tasks" v-bind:key="task.id">
<td class="table-text"><div>{{ task.name }}</div></td>
<!-- Task Delete Button -->
<td>
<button @click="deleteTask(task.id)" class="btn btn-danger">
<i class="fa fa-btn fa-trash"></i>Delete
</button>
</td>
</tr>
ボタンアクション
@click
で対応するmethodsを呼び出す
<!-- Add Task Button -->
<div class="form-group">
<div class="col-sm-offset-3 col-sm-6">
<button @click="addTask()" class="btn btn-default">
<i class="fa fa-btn fa-plus"></i>Add Task
</button>
</div>
</div>
methods
fetchAPIで各種Laravel APIにリクエストをする
fetchTasks
タスク一覧取得
URI:api/tasks
Method:GET
fetchTasks() {
fetch('api/tasks')
.then(res => res.json())
.then(res => {
this.tasks = res.data;
})
.catch(err => console.log(err))
},
addTask
新規タスク追加
URI:api/task
Method:POST
addTask() {
this.errors = [];
if(!this.task.name) {
this.errors.push('Name required.');
return;
}
fetch('api/task', {
method: 'post',
body: JSON.stringify(this.task),
headers: {
'content-type': 'application/json'
}
})
.then(res => res.json())
.then(data => {
this.task.name = '';
this.fetchTasks();
})
.catch(err => console.log(err))
},
deleteTask
タスク削除
URI:api/task/{id}
Method:`DELETE
deleteTask(id) {
fetch(`api/task/${id}`, {
method: 'delete'
})
.then(res => res.json())
.then(data => {
this.fetchTasks();
})
.catch(err => console.log(err))
}
簡易的バリデーション処理
addTask() {
this.errors = [];
if(!this.task.name) {
this.errors.push('Name required.');
return;
}
<!-- Display Validation Errors -->
<div v-show="errors.length" class="alert alert-danger">
<strong>Whoops! Something went wrong!</strong>
<br><br>
<ul>
<li v-for="error in errors" v-bind:key="error">{{ error }}</li>
</ul>
</div>
以上