【Axiosの実装】Laravel+Vue.jsでのDB連携

はじめに

Vue.jsでLaravelのDBを弄る方法をまとめました。

前回はAjaxで非同期処理を行っていましたが、今回はAxiosを使った実装理解をしていこうと思います。

ちょび
今回は敢えて認証機能の実装せず超ミニマム実装です。

※前回記事

【Ajax(API)の実装】Laravel+Vue.jsでのDB連携

プロジェクトの作成

事前準備

Axiosを使うまでの実装。

※以下のやり方を踏まえて、色々な編集工程を極限までそぎ落としてみました。

【感想】Laravel+PostgreSQL+Vue.jsでSPA開発【チュートリアル】

・TodoController作成。indexアクションメソッドを追記。(welcomeビューをそのまま使います)

php artisan make:controller TodoController

編集

public function index() {
        return view('welcome');
      }
}

・ルーティングの設定。web.phpを編集。Webルートの制限が便利です。

<?php
Route::get('/{any}', function () {
    return view('welcome');
})->where('any', '.*');

全てのURLでwelcome.blade.phpを表示するようになります。

・マイグレーションファイルの作成

php artisan make:migration create_todos_table

編集

Schema::create('todos', function (Blueprint $table) {
            $table->bigIncrements('id'); // 削除・更新で重要
            $table->string('todo');
            // $table->integer('user_id'); // ここを削除
            // $table->timestamps(); // 今回は時間も不要なので削除Axiosの実装で必要なことがわかりました。
        });

※6.8だとuser_idの紐づけはデフォルトで記述されていないのでそのままでOKです。

反映

php artisan migrate

・モデルの作成

php artisan make:model Todo

・Vue.jsの実装

npm i
npm run dev
npm run watch

・welcome.blade.phpの編集

<script src="{{ asset('js/app.js') }}" defer></script>
<meta name="csrf-token" content="{{ csrf_token() }}"> // post送信時にトークンが必要
<div id="app">
  <h2>TODO アプリケーション</h2>
  <example-component></example-component>
</div>

現状こんな感じです。

注意(Laravel6.8の場合)
Laravel6.8だとデフォルトでVue.jsが入っていません。package.jsonを編集してからインストールする必要があります。

package.jsonに追記

"vue": "^2.5.17",

js/app.jsの編集

require('./bootstrap');
window.Vue = require('vue');
Vue.component('example-component', require('./ExampleComponent.vue').default);
const app = new Vue({
    el: '#app'
});

js/ExampleComponent.vueの作成

今回編集が不要な部分

・Karnel.phpでの認証保持用(セッション・クッキー)のミドルウェア設定。

・Todoモデルの編集。(ユーザーとのリレーション設定は今回なし。)

ちょび
Todoモデルに関しては、モデルを使わずにリクエスト&DBクラスで実装も検討しましたが、結局CRUDの記述で冗長になりそうだったので、使うことにしました。Eloquent便利・・・。

機能実装

・ExampleComponent.vueの編集

※ここは前回の完成コード流用。

・api.phpの編集

<?php
Route::get('/','TodoController@get');
Route::post('/','TodoController@post');
Route::delete('/{id}','TodoController@delete');
Route::put('/{id}','TodoController@update');

・TodoControllerの編集

※前回のコードから認証部分のコードを削除。

ちょび
ここまででAjaxwを用いた非同期処理の実装が完了しました。

Axiosの実装

ここからAjaxからAxiosのコードに変えていきます。

axiosはブラウザやnode.js上で動くPromiseベースのHTTPクライアント。

第一引数にパラメータ付きのURLを指定し、.then()で通信が成功した際の処理を書く。

response.dataにデータが入る。

ちょび
ちなみにAxiosはデフォルトでbootstrap.js⇒app.jsで読み込みされて、使えるようになっています。

データの取得

mounted() {
  axios.get('/api')
  .then(res =>{
      this.todos = res.data;
  })
}
ちょび
これだけで取得できちゃいました。記述量がだいぶ少なくなって驚きです。
補足

<?php
use App\Todo;
Route::get('/',function(){
    return response()->json(Todo::all());
});
ちょび
api.phpにモデルを追記して編集すればルーティングファイルだけでも実装できました。コントローラ使わずに全て実装しようかな??笑

データの削除

※データの追加を最初に試したところ全然できなかったので、削除に挑戦。

deleteTodo(id) {
  var data = {};
  axios.delete("/api/" + id, JSON.stringify(data)).then(() => {
    this.getTodoList();
  });
},
ちょび
削除は正直びっくりするくらいあっさりできました。

また。JSON.stringfy()メソッドの記述はなくても機能しました。これはデータが1つしか入っていないからかもしれません。

データの追加

※追加の実装はかなり苦戦しました。

addTodo() {
  var data = {
      todo: this.todo_form
      // insertされる内容。カラムに合わせる。
  };
  axios.post('/api', data).then(() => {
  this.getTodoList();
  });
},
ちょび

備忘録:【Laravel x Vue.js】SPAクイズアプリケーションを作ってみよう! 最初はこちらの教材(7-5から)を参考にしましたが、POST送信に関してはformタグでURL遷移する実装(会員登録後TOPページへ移動。)になっていました。

データの更新

以下でとりあえずPUTメソッドが使えることを確認。

updateTodo(id) {
 axios.put("/api/" + id, {todo: "edit"}).then(() => {
    this.getTodoList();
  });
},

その後チュートリアル通りfilterメソッドを使って実装。

updateTodo(id) {
  var data = {
    todo:this.todos.filter(function(value){return value.id === id})[0].todo
  };
 axios.put("/api/" + id, data).then(() => {
    this.getTodoList();
    alert('更新が完了しました。')
  });
},
ちょび
filterメソッドの理解が難しい。わかりづらかったので更新後、アラートが出るようにもしてみました。

完成

ソースコード

躓いた点

①トークンの実装方法がわからず。⇒結果として実装できていないもののなぜか動く。

(コンソールで500エラーを確認。トークンの実装周りが原因だと思っていたが違った。)

追記:デフォルトではAPIはトークンを使用しない設定になっているっぽい。Karnel.phpで設定弄れる。クッキー周りの対応法はこちらの教材が詳しく扱ってる。

・GoogleConsoleのNetworkタグでapi通信の挙動を確認したところ以下のような内容の記述。

messageSQLSTATE[42S22]: Column not found: 1054 Unknown column ‘updated_at’ in ‘field list’ (SQL: insert into `todos` (`todo`, `updated_at`, `created_at`) values (テストだよよ, 2020-04-20 07:54:19, 2020-04-20 07:54:19))
exceptionIlluminate\Database\QueryException
fileC:\xampp\htdocs\memo_noauth6.8\vendor\laravel\framework\src\Illuminate\Database\Connection.php
line669

⇒updatad_atカラムがないことでエラーが起きていたので、カラムを追加しなおしたところ動いた。これは思わぬ落とし穴でした。。。(おそらく根本的なDatabaseの設定を弄れば変えられると思うけど。。。)

②PUTメソッドが使えない。※この後POSTメソッドに変えても同様のエラー。⇒axiosメソッドのルーティングでapiの後ろに/入れ忘れ

ちょび
参考:Laravel 6.x ルーティング
HTMLフォームはPUTPATCHDELETEアクションをサポートしていません。
擬似メソッドやら使うと行けるらしい。でもDELETE使えてるな~と思ってたら案の定これは原因ではなかった。
補足
・Laravelでは変数を返却すると自動的にJSONに変換して表示を行うそうです(教材6-3参考)。

Route::get('/',function(){
    $todo = Todo::all();
    return $todo;
});

・見通しを良くするためにTodoControllerに記載していたアクションメソッドは全てapi.phpで記載しました。

おわりに

Ajaxから本来実装が簡単であるはずのAxiosに置き換えるだけでかなり苦戦してしまいました。

ですが、おかげでLaravel×Vue.jsの理解が深まりました。

やっとこさLaravel×Vue.jsのアプリ制作にとりかかれそうです。

また、今回トークン処理(+Vue.js側での認証状態の維持)の対応を踏まえるとログイン/会員登録機能はLaravel側で実装したほうが良い気がしました。
振り返ったらHC教材ではVuexまで活用して実装しているし、TechpitSPA開発教材(7-5)も同じくトークン処理で記述が多め。
勉強がてらならいいけど、実際に使うとなると実装も難しいしかえって管理が大変そう。
しかもログイン/会員登録画面って別でページ用意すること多いし、処理後トップページなどに遷移するケースがほとんど

参考:Vue + Vue Router + Vuex + Laravelで写真共有アプリを作ろう (7) 認証機能とVuex Part.2

一つ目の課題は、ページをリロードしたときに認証状態が維持できない点です。

試しにログインした状態でページをリロードしてみてください。ヘッダーとフッターにログインリンクが表示され、ログアウト状態に戻ってしまうはずです。

ページをリロードすると Vue アプリケーションが再作成されるので、当然 user ステートも初期値である null に戻ってしまいます。それで見た目はログアウトしてしまうのです。

ただしサーバサイドのセッション的にはまだログインしているので、もう一度ログインしようとするとユーザーデータではなく /home へのリダイレクトレスポンスが返却されます。そのためログインしているような見た目だがユーザー名が表示されないという中途半端な表示になります。

この挙動を修正するために、ログインユーザーを返却する API を追加して、最初にログインユーザーを取得してから Vue アプリケーションを生成するように起動スクリプトを変更しましょう。

また、一応 /home へリダイレクトさせるミドルウェアも修正しておきます。

参考

公式

Array.prototype.filter()

参考

Laravel + Vue.js + axiosで非同期postリクエストを送ろうとし時のハマったポイント(全部うっかりミス)をまとめた 追加処理の実装

laravel で vue.js , axios を使う こちらは取得のみの実装

モジュール化(importとrequireの違い)

【Ajax】axiosを使って簡単にHTTP通信

Documentインターフェース ⇒あらゆる種類の文書に対して共通のプロパティやメソッドを提供。

vue.jsを使ってaxiosを学ぶ 一通りCRUDの解説あるが難しい。

vue.js と axios を使って Web API にアクセスする POSTの実装。むずい。。。

Laravel + Vue.js + vue-router + axios.postでSPA作成(記事投稿機能) anyの実装も参考になる。

axiosライブラリを使ってリクエストする axiosは第二引数に登録・更新データを持たせる。

Laravelで405や419エラーに遭遇した場合の対処法 ルーティングの定義漏れ

参考:Laravel でAjax をデバッグする方法
Google Developper tool を使いましょう。
・500番台→パスは合っているがphp の処理中にエラーが発生している
・400番台→パスが間違っている
・200→処理は成功している

axiosのヘッダーにtokenを埋め込んで常時使えるようにする

ajaxでエラーが出てしまう。【laravel5】 Ajaxだとトークンでの処理解決方法が結構出てくる。

$ is not definedエラーの解決方法

Laravel5でのAjaxでPOSTするときのValidation(Axios利用している。)

Laravel + Vue で問い合わせフォームをつくる メール送信機能でCSRF,TOKENの実装はなし。

Laravel + Vue.js + axiosでメール送信する方法を解説 上に同じ。

Laravel + vue.jsでシンプルファイルアップロード Axios側のトークン設定の記述なし。

POSTとPUTとPATCHの使い分けについて

Laravel5.6とVue.jsで簡単なシングルページアプリケーション POSTメソッドに関してaxiosで特に配慮するような記述はない。

【JavaScript入門】alert(アラート)メッセージはこれで完璧。使い方を総まとめ!

コメントを残す