Laravel を利用した CRUD の SPA 作成 3 検索画面作成編

Vue.js を Laravel で使用する準備

まずは Vue.js を Laravel で使用する準備を行います。「package.json」に下記を追加します

    "devDependencies": {
        "axios": "^0.19",
        "cross-env": "^5.1",
        "laravel-mix": "^4.0.7",
        "lodash": "^4.17.13",
        "resolve-url-loader": "^2.3.1",
        "sass": "^1.15.2",
        "sass-loader": "^7.1.0",
        "vue": "^2.5.7", 
        "vue-router": "^2.3.0",       
        "bootstrap": "^4.0.0"
    }

それでは ホスト(私の場合はWindows) で「npm」コマンドを実行します。

なお、Node.js をインストールしていない場合は、ここなどが参考になると思います。

Vagrant の Linux OS でもできるのですが、たいていはシンボリックリンクうんぬんで失敗します。このためホストOS で行うのがおすすめです。

npm install

それでは Laravel のほうで、サーバーから返却される HTML を設定します。

<!DOCTYPE html>
<html lang="{{ app()->getLocale() }}">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>SPA</title>
    <link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
    <div id="app">
        <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
            <div class="container">
                <h2>SPA</h2>
            </div>
        </nav>
        <main id="app" class="container" style="padding-top: 60px;">
            <router-view></router-view>
        </main>
    </div>
    <script src="{{ asset('js/app.js') }}"></script>
</body>
</html>
Route::get('{any}', function () {
    return view('spa');
})->where('any','.*');

デザイン面をちょっと整えるために「bootstrap」をインストールします。

@import "~bootstrap/scss/bootstrap";
 npm run dev

それで「http://homestead.test/」にアクセスするとページが表示されます。

長かった。ここまで本当に。だがまだ検索のロジックが残っている、俺たちの戦いはここからだ ~ 完

検索ロジック作成 Laravel側

ということで、Laravel での検索に必要な機能を実装してきます。

コントローラー等は PHP がインストールされているゲストOS(Vagrant)で実行したほうが良いです。

vagrant ssh
cd /code/spa
php artisan make:controller ItemsController --resource

作成されたコントローラーは DBに格納されている Item を返却されるようコードを追記します。

    public function index(Request $request) {
        $itemName = $request->input('item_name', '');
        $items = \App\Item::where('item_name', 'LIKE', "%$itemName%")->get();
        return response($items);
    }
Route::get('items', 'ItemsController@index');

http://homestead.test/api/items
↑全件が Json で返却される

http://homestead.test/api/items?itemName=%E3%81%82
↑引数に itemName をつければあいまい検索ができる

検索ロジック作成 Vue.js 側

まずは、変更があるたびごにょごにょやってくれる、素晴らしいコマンドをホストOSで実行します。

npm run watch-poll

それでは Vue のひな形を作ります。

<template>
  <div>
    <div class="input-group mb-3">
      <div class="input-group-prepend">
        <span class="input-group-text">検索</span>
      </div>
      <input type="text" class="form-control" v-on:blur="fetchItems" v-model="searchText">
    </div>
    <table class="table table-bordered table-dark">
      <thead>
        <tr>
          <th scope="col">Id</th>
          <th scope="col">名前</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="item in items">
          <th scope="row">{{ item.id }}</th>
          <td>{{ item.item_name }}</td>
        </tr>
      </tbody>
    </table>
  </div>
</template>
<script>
    export default {
        created() {
        },
        data() {
            return {
                items: [],
                searchText: '',
                message: null
            }
        },
        methods: {
        }
    }
</script>
import Vue from 'vue'
import VueRouter from 'vue-router'
import itmeIndex from './components/items/Index.vue'
require('./bootstrap');
Vue.use(VueRouter)
const router = new VueRouter({
    mode: 'history',
    routes: [
        { path: '/', component: itmeIndex }
    ]
})
const app = new Vue({
    router,
    el: '#app'
})

「/」(ルートパス)でアクセスした場合「Index.vue」を使用するようルーティングします。
テンプレートは「spa.blade.php」の「<router-view></router-view>」に描写されることになります。
これでいったんアクセスします。

「Index.vue」の<template>に記載された HTML が <router-view> に描写されました。 さてそれでは、デフォルトデータの表示と検索を実装してきます。
<template>
  <div>
    <div class="input-group mb-3">
      <div class="input-group-prepend">
        <span class="input-group-text">検索</span>
      </div>
      <input type="text" class="form-control" v-on:blur="fetchItems" v-model="searchText">
    </div>
    <table class="table table-bordered table-dark">
      <thead>
        <tr>
          <th scope="col">Id</th>
          <th scope="col">名前</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="item in items">
          <th scope="row">{{ item.id }}</th>
          <td>{{ item.item_name }}</td>
        </tr>
      </tbody>
    </table>
  </div>
</template>
<script>
    export default {
        created() {
            this.fetchItems()
        },
        data() {
            return {
                items: [],
                searchText: '',
                message: null
            }
        },
        methods: {
            fetchItems() {
                axios.get('/api/items', {params: {item_name:this.searchText}}).then((res)=>{
                    this.items = res.data
                })
            }
        }
    }
</script>

テンプレート

「v-on:blur」にてフォーカスアウト時にイベントを発火させ検索しに行くよう設定します。
「v-for」取得したデータをループさせて一覧表示します。

スクリプト

まず最初にcreated で初期化時に初期データ取得をする関数を呼びます。
axios で Laravel に問い合わせて結果を格納します。

ということで、検索画面が完成しました。

JavaScript, PHP

Posted by admin