「技術」カテゴリーアーカイブ

【Laravel】【ホテル予約管理】ユーザーの権限管理を行う

最新ソースはこちら(gitHub)

https://github.com/takishita2nd/hotel-mng

さて、お次の課題は、

  • 一般ユーザーからでも予約登録ができる
  • レスポンシブ対応にする

です。

で、そのために必要になるのが、ユーザーの権限管理というものです。

具体的には、管理者用のアカウントを登録して、管理者アカウントからは今までのフル機能が使用できる。

その一方で、通常ユーザーの場合は、一部の機能だけが使用できる、という感じです。

Laravelの権限管理の方法は色々あるようですが、今回は一番簡単なGATEを使用した方法を採用しようと思います。

この方法なら、新たに特別なプラグインを使用する必要がないためです。

では、Userテーブルに還元を管理するカラムroleを追加します。

$ php artisan make:migration add_column_role_users_table --table=users
class AddColumnRoleUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->tinyInteger('role')->default(0)->after('password');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->dropColumn('role');
        });
    }
}
$ php artisan migrate

単純にrole=0が一般ユーザー、role=1が管理者アカウントとします。

では、Seederを使用して、管理者アカウントを予め追加しておきます。

(これを行わないと、管理者権限を与えるユーザーが存在しないことになるので、運用できません!)

$ php artisan make:seeder UsersTableSeeder
class UsersTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        DB::table('users')->insert([
            'name' => 'manager',
            'email' => 'manager@gmail.com',
            'password' => bcrypt('manager'),
            'role' => 1,
        ]);
    }
}
$ composer dump-autoload
$ php artisan db:seed --class=UsersTableSeeder

登録できました。

次は、AuthServiceProviderのboot()に処理を追加して、GATEによる権限の定義を記入します。

    public function boot()
    {
        $this->registerPolicies();

        Gate::define('manager', function ($user) {
            return ($user->role == 1);
        });
        Gate::define('user', function ($user) {
            return ($user->role == 0);
        });
    }

これで、role=1(manager)、role=0(user)がGATEによって定義されました。

では、Viewを書き換えて、一般ユーザーには不要なメニューを表示させないようにします。

<div class="panel-body">
    <detail-component></detail-component>
    <div>{{ Html::Link('/management/create', '追加', ['class' => 'btn']) }}</div>
</div>
@can('manager')
<div>{{ Html::link('/management/schedule', 'スケジュール', ['class' => 'btn']) }}</div>
<div>{{ Html::link('/management/total', '集計', ['class' => 'btn']) }}</div>
<div>{{ Html::link('/room', '部屋一覧へ', ['class' => 'btn']) }}</div>
<div>{{ Html::link('/management/checkout', '本日のチェックアウト', ['class' => 'btn']) }}</div>
@endcan

ポイントは@can(権限)〜@canend。

@can(権限)に権限の名前を入れることで、ユーザーの権限に対して@can(権限)〜@canendの表示を切り替えることができます。

manager権限

一般ユーザー

こんな感じで、表示の切り替えができました。

では、次回からは一般ユーザーの使い勝手がいいように修正していきましょうか。

Ps4のリモートプレイを試す(PC編)

こちらではiOSの場合についてまとめたんですが、

実はリモートプレイって、PCでもできるんですね。

対応OSはWindowsとMacOSです。

https://remoteplay.dl.playstation.net/remoteplay/lang/jp/

やり方は上のサイトからアプリをダウンロード、インストールして、アプリを起動して、PSアカウントでログインする。

ここはiOSと同じ。

PC版で何が違うかというと、PS4のコントローラーはUSBケーブルで優先接続できるというところ。

PS4本体じゃないですよ、PC本体にですよ。

(逆にPCにコントローラーを接続しないと操作ができない)

もちろん、PCにBluetoothのレシーバがあればBluetoothでも接続できるのですが、ペアリングすると、iOSと同じようなペアリング問題が発生します。

でもPCに優先接続なら、優先接続中はPCに、ケーブルを外せばPS4本体に接続されます。

なので、ペアリング問題とは無縁。

まぁ、ネットワークを通じて画面を転送しているので、フレームレートが落ちるので、動きはなめらかじゃないですけどね。

でも、無双OROCHI3とかは問題なくプレイできた。

いいね。悪くない。

PS4のリモートプレイを試す(iOS編)

PS4のリモートプレイは、元々Xperia端末のみで可能でしたが、ちょっと前のアップデートで、他の端末でも利用可能になりました。

しかも、Android端末だけで無く、iOSやPCでも可能になっています。

というのは、今自分はPixel3を使用しているのですが、Pixel3でリモートプレイをしようと思ったら、画面縦置き固定でゲーム画面は上1/3以下のサイズで、画面タップでプレイする、というものでした。

たぶん、PS4コントローラーをベアリングすれば使えると思いますが。

でももっと大きな画面でプレイしたい。

Androidタブレットだとどうなるんですかね?

そもそもAndroidタブレットって、いまそんなに需要無い?(しらんけど)

オイラはiPad Proを持っているので、これに表示できれば、まだマシになるんじゃないかと思いました。

なので、検索。

ありました。

仕組みは、Androidのリモートプレイと同じで、LAN/Wifi経由で画面を表示させます。

アプリを起動して、PSアカウントでログインすると、自動的にネットワーク上のPS4を探してくれます。

ゲーム画面がほぼ全画面に表示され、コントローラーと同じ位置に、各ボタンに対応するタッチエリアがあります。

しかも、PS4コントローラーをBluetoothでiPadとペアリングすれば、PS4コントローラーでプレイできます。

リモートプレイを使用すると、PS4とペアリングしているコントローラーは切断されて使用できないので、コントローラーをiPadとペアリングして使用する必要があります。

ただ、これを元に戻すのが面倒で、まず、iPad側からペアリングを削除する必要があり(コントローラーの電源を入れると、勝手にiPadに接続されます)、PS4とペアリングするにはUSBケーブルで接続する必要があります。

この接続が面倒で、純正ケーブルか、充電・通信ケーブルを使用する必要があります。(充電専用ケーブルではPS4本体とペアリングできない)

まぁ、充電専用ケーブルはケーブル自体が細いから、ケーブルの太さで区別はできるのですが。

まぁ、ややこしい、ということです。

まぁ、こういうリモートプレイもできるんだぞってことで。

Wifi経由で画面に表示させているので、フレームレートはちょっと低い感じがします。

【laravel】【ホテル予約管理】チェックアウト時刻一覧の問題を解決する

本日から本気出す。

前回までの状況はこちら

最新ソースはこちら(gitHub)

https://github.com/takishita2nd/hotel-mng

実は、このリポジトリの処理には重大な問題があります。

    public function getCheckoutList()
    {
        $ret = array();
        $index = 0;
        $checkout = ReserveManagement::select('rooms.name as roomname', 'checkout')
                                    ->leftJoin('reserve_management_room', 'reserve_managements.id', '=', 'reserve_management_room.reserve_management_id')
                                    ->leftJoin('rooms', 'reserve_management_room.room_id', '=', 'rooms.id')
                                    ->get();
        date_default_timezone_set('Asia/Tokyo');
        $today = date("Y-m-d");
        foreach ($checkout as $value) {
            $str = explode(" ", $value->checkout);
            if($today == $str[0]) {
                $value->checkout = $str[1];
                $ret[$index] = $value;
                $index++;
            }
        }
        return $ret;
    }

全レコードを取得したあと、日付チェックをおこない、必要なデータのみを取得する、というやり方ですが、このやり方では、大量のデータをデータベースから取得し、PHPで処理する、というやり方なので、サーバに大きな負荷がかかります。

これを解消するには、データベースから取得するデータの量を度絞らなければなりません。

なので、以下のように修正します。

    public function getCheckoutList()
    {
        date_default_timezone_set('Asia/Tokyo');
        $today = date("Y-m-d 00:00:00");
        $tomorrow = date("Y-m-d 00:00:00", strtotime("tomorrow"));
        return ReserveManagement::select('rooms.name as roomname', 'checkout')
                                    ->leftJoin('reserve_management_room', 'reserve_managements.id', '=', 'reserve_management_room.reserve_management_id')
                                    ->leftJoin('rooms', 'reserve_management_room.room_id', '=', 'rooms.id')
                                    ->whereBetween('checkout', [$today, $tomorrow])
                                    ->get();
    }

クエリビルダにwhereBetween()を追加し、BETWEEN節を追加しました。範囲は、アクセス当日の0時から次の日の0時です。

これだけで必要なデータは全て取れましたので、それをそのまま返します。

動作結果は前回と同じになります。

うん、こっちのほうがコードもスッキリしていいですね。

【自作PC】32GBのメモリを使い切ってみよう

これを検証する前に、アイドル状態(Windowsを立ち上げてデスクトップを表示しているだけ)でどれだけメモリを使用しているかを見てみます。

とにかく、不要な常駐アプリも終了させて、こんな感じでした。

使用中のメモリサイズが3.5GBです。

4GBしか積んでいなかったら残りが0.5GBしかないので、これではすぐにページングが発生してしまうという事になりますね。

ページングが発生するとPC全体の処理速度が低下します。

ちなみに、自分の環境では常駐アプリも含めると、こんな感じになります。

3.9GBですね。

この状態から、Word、Excel、Acrobat Readerを開くと、こんな感じです。

4.7GB。メモリが4GBしか積んでいなかったらページングが発生しています。

さて、ここから本題に入りまして。

どんどん、アプリを起動して、32GBのメモリを使い切ってみよう。

ここで起動したアプリは、

  • マインクラフトBE版
  • マインクラフトJava版
  • DMM Games
  • Word
  • Excel
  • Acrobat Reader DC
  • Visual Studio 2019
  • Android Studio
  • Unity
  • Vivaldi
  • Google Chrome
  • Cyberlink PowerDirector

たくさんのドキュメントを開いて、プログラミングしている途中でYouTubeなどを見ながらゲームをする、と言う設定です。

そんな使い方するヤツいねーよ!

結果はこうなりました。

メモリ半分使う前に、CPUが限界に達しました。

CPUの処理が追いついていないので、全体的にモッサリした動きになってました。

しかし、PowerDirectorでたくさんの動画ファイルを使用したりとか、VMWareなどの仮想環境を複数立ち上げていた場合だったら、32GBを使い切ることができるかもしれません。

たぶん、メモリ16GBを割り当てたLinux仮想環境を立ち上げても快適に動作するよ。

でも、逆に言えば、そんなヘビーな使い方をしない限りは、メモリ16GBあれば、十分ということになります。

そしてなにより、CPUも強化しないと、性能を生かすことができないということですね。

うーむ、贅沢な道楽。

でも次の収入があるまで我慢。

【自作PC】自作PCに限っての2019振り返り

全体的な振り返りはこちらにまとめましたが、

ここでは自作PCに限定して振り返ります。

いやーメモリ32GBのRyzenPC、メインPCとしてバリバリ活躍しています。

でもその道も平坦では無くて。

特に躓いたのが、メモリ4枚挿し。

結局諦めましたからね。

拡張性を考慮してメモリスロット4つのマザーボードを購入しましたが、これだったら2枚のマザーボードでも良かったじゃん、って感じです。

2枚差しだったらもっと安いマザーボード買える。

そして、メモリーはショップで相性保証を付ける方が良い。

自作PCで動作しない、という症状は、主にマザーボードとメモリーの相性だったりします。あとは、きちんと刺さってなかったり。

例えばツクモの相性保証を付ければ、相性が合わなくて動作しなかった場合、1ヶ月以内だったらパーツ交換してくれるというやつです。

相性問題が発生してもリスクが少ないので、相性保証付けた方が、結果敵にお得です。

あと、コストのことを考えたら、AMD系の方が圧倒的有利だと思いました。

世代が変わってもソケットの規格が同じ(AM4)なので、マザー自体を変えなくちゃいけない、と言うことが少ないためです。

Intel系は世代毎にソケットの規格が異なったりするので、マザーを変える必要があります。

マザーを変えると言うことは、また相性問題が発生する可能性がある、ということです。

このリスクを考えると、AMD系のほうがかなりお得だと思います。

今Ryzen5 3400Gを使用していますが、これをワンランク上の第3世代Ryzen7に買えるとしても、ソケットの規格が同じAM4なので、CPUを交換するだけで対応出来ます。

まぁ、AMD系CPUの欠点は足が曲がりやすいので取り扱い注意と言うことですかね。

最近大きな買い物をしてしまったのでd、次の収入があるまで我慢ですが、次は第3世代のRyzenにパワーアップさせたいですね。

【Laravel】【Vue.js】【ホテル予約管理】チェックアウト一覧を表示

前回までの状況はこちら

予約一覧から本日チェックアウトする部屋を探して画面に表示させます。

View

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <div class="panel panel-default">
                <div class="panel-heading">本日のチェックアウト時刻</div>

                <div class="panel-body">
                    <table class="checkout">
                        <tr>
                            <th class="name">部屋</th>
                            <th class="time">チェックアウト時刻</th>
                        </tr>
                    @foreach ($Lists as $list)
                        <tr>
                            <td class="name">{{ $list->roomname }}</td>
                            <td class="time">{{ $list->checkout }}</td>
                        </tr>
                    @endforeach
                    </table>
                </div>
                <div>{{ Html::link('/management', '戻る', ['class' => 'btn']) }}</div>
            </div>
        </div>
    </div>
</div>
@endsection

ルーティング

Route::get('/management/checkout', 'RegisterManagementController@checkout');

コントローラー


    /**
     * 当日のチェックアウト時刻一覧を表示
     */
    public function checkout(Request $request)
    {
        return view('register.checkout',
                        [
                            'Lists' => $this->registerManagement->getCheckoutList()
                        ]);
    }

リポジトリ

    public function getCheckoutList()
    {
        $ret = array();
        $index = 0;
        $checkout = ReserveManagement::select('rooms.name as roomname', 'checkout')
                                    ->leftJoin('reserve_management_room', 'reserve_managements.id', '=', 'reserve_management_room.reserve_management_id')
                                    ->leftJoin('rooms', 'reserve_management_room.room_id', '=', 'rooms.id')
                                    ->get();
        date_default_timezone_set('Asia/Tokyo');
        $today = date("Y-m-d");
        foreach ($checkout as $value) {
            $str = explode(" ", $value->checkout);
            if($today == $str[0]) {
                $value->checkout = $str[1];
                $ret[$index] = $value;
                $index++;
            }
        }
        return $ret;
    }

ここまでアップデートする過程で、checkoutがnullになるケースがあったためか、データベースで日付指定でwhereすると、うまく行かないので、結局、全テーブルから日付を全部チェックする、という処理になりました。

もっとうまくできる方法ないかねぇ。

あと、タイムゾーンも考慮しないと、日付の判定がうまく行かないときがあるので、date()関数を使用するときは注意。

こんな感じで最終チェック後、提出します。

【自作PC】メモリ32GBの世界へようこそ

いやー買っちゃいました。

16GBのメモリ2枚です。

4枚差しが上手くいかないものの、32GBの夢が捨てきれず、買っちゃいました。

32GBの世界へようこそ。

念のためベンチマークを走らせます。

念のため、というのは、もう十分メモリがありすぎるので、劇的な変化は期待していないと言うことです。

もはや道楽の世界。

ちなみに、前回のベンチマークの結果はこちら。

PCMARKでのスコアは若干アップ。

FF14、FF15は誤差のレベルなので、ほとんど変化無しですね。

予想通り。

メモリが4GB→8GBに増やした場合は、プログラム実行時にメモリに空きが無い場合、一番使用されていないメモリのデータをストレージに吐き出して、メモリの容量を確保します。

そして、吐き出したデータが必要になったときにメモリに読み込みます。

この一連の処理をページング、またはスワッピングといいます。

情報処理の試験に出ます。

このときのストレージへのアクセスが、メモリ不足によってPCが遅くなる最大の要因なのです。

でも、16GB以上になると、ほとんどページングが発生することがない。(それだけ十分過ぎるメモリがあるので)

じゃあ、なぜメモリを32GBに増やしたかというと、

道楽ですよ。

とはいえ、このメモリだけでそれなりのお金を使ってしまったので、当分の間は大きな買い物できないな。

次は・・・CPUかな。

パーツ型番価格
CPURyzen 5 3400G20680
マザーボードPRIME A320M-A7544
メモリCT2K16G4DFD822614280
電源KRPW-L5-750W/80+6256
ケースCC-9011086-WW5099
SSDGH-SSDR2SA1202178
M.2SSDSCKKW480H6X15980
グラフィックボードSAPPHIRE PULSE RADEON RX 570 8G GDDR514800
DVDドライブIHAS324-17/A2020
OSWindows 10 Pro3259
電源ユニットネジ200
合計82298

【Laravel】【Vue.js】【ホテル予約管理】予約の削除を実装する

前回までの状況はこちら

最新ソースはこちら(gitHub)

https://github.com/takishita2nd/hotel-mng

予約詳細画面に削除ボタンを設置します。

                <button @click="closeModal">close</button>
                <button v-if="edit_flg == false" @click="onClickEdit">編集</button>
                <button v-else @click="onClickSave">保存</button>
                <button v-if="edit_flg == false" @click="onClickDelete">削除</button>
            onClickDelete: function() {
                var self = this;
                this.param.year = this.selectYear;
                this.param.month = this.selectMonth;
                this.param.room = this.selectRoom;
                this.param.id = this.contents.id;
                axios.post('/api/delete', this.param).then(function(response){
                    self.registers = [];
                    self.updateRegisters(self, response.data.registerLists);
                    self.closeModal();
                }).catch(function(error){
                    self.error_flg = true;
                    self.error_message = error.response.data.errors;
                });
            },
            updateRegisters: function(self, registerLists){
                registerLists.forEach(element => {
                    self.registers.push(
                        {
                            id:element.id, 
                            name:element.name,
                            address:element.address,
                            phone:element.phone,
                            num:element.num,
                            roomid:element.roomid,
                            room:element.room,
                            days:element.days,
                            start_day:element.start_day, 
                            checkout:element.checkout
                        }
                    );
                });
            }

APIへのルーティング

Route::post('/api/delete', 'ApiController@delete');
    public function delete(Request $request)
    {
        $this->registerManagement->deleteById($request->id);
        return response()->json(['registerLists' => $this->registerManagement->getListByMonth(
            $request->year,
            $request->month,
            $request->room
        )]);
    }

実際に削除したら、レスポンスで予約一覧を返し、一覧を最新の状態で表示してもらいます。

あとは、一覧更新処理が共通しているので関数化。

難なく設置できました。

・・・追加処理もモーダル化する?

【Laravel】【Vue.js】【ホテル予約管理】予約の編集を行う

前回までの状況はこちら

前回の予約詳細画面。

これに、編集ボタンを追加して、予約編集できるようにします。

これが思いの外大変だった。

まずはテンプレートを編集。

        <div id="overlay" v-show="showContent">
            <div id="content">
                <p v-if="error_flg == true" class="error">{{error_message}}</p>
                <table class="edit">
                    <tbody>
                        <tr>
                            <th>名前</th>
                            <td v-if="edit_flg == true"><input type="text" v-model=contents.name /></td>
                            <td v-else>{{ contents.name }}</td>
                        </tr>
                        <tr>
                            <th>住所</th>
                            <td v-if="edit_flg == true"><input type="text" v-model=contents.address /></td>
                            <td v-else>{{ contents.address }}</td>
                        </tr>
                        <tr>
                            <th>電話番号</th>
                            <td v-if="edit_flg == true"><input type="text" v-model=contents.phone /></td>
                            <td v-else>{{ contents.phone }}</td>
                        </tr>
                        <tr>
                            <th>人数</th>
                            <td v-if="edit_flg == true">
                                <select v-model=contents.num>
                                    <option v-for="num in nums" v-bind:value="num.value">{{ num.text }}</option>
                                </select>
                            </td>
                            <td v-else>{{ contents.num }}</td>
                        </tr>
                        <tr>
                            <th>宿泊部屋</th>
                            <td v-if="edit_flg == true">
                                <select v-model="contents.roomid">
                                    <option v-for="room in rooms" v-bind:value="room.id">{{ room.name }}</option>
                                </select>
                            </td>
                            <td v-else>{{ contents.room }}</td>
                        </tr>
                        <tr>
                            <th>宿泊日数</th>
                            <td v-if="edit_flg == true"><input type="number" v-model=contents.days /></td>
                            <td v-else>{{ contents.days }}</td>
                        </tr>
                        <tr>
                            <th>宿泊日</th>
                            <td v-if="edit_flg == true"><input type="date" v-model=contents.start_day /></td>
                            <td v-else>{{ contents.start_day }}</td>
                        </tr>
                        <tr>
                            <th>チェックアウト</th>
                            <td v-if="edit_flg == true">
                                <select v-model="contents.checkout">
                                    <option v-for="time in timeList" v-bind:value="time.key">{{ time.value }}</option>
                                </select>
                            <td v-else>{{ contents.checkout }}</td>
                        </tr>
                    </tbody>
                </table>
            <p>
                <button @click="closeModal">close</button>
                <button v-if="edit_flg == false" @click="onClickEdit">編集</button>
                <button v-else @click="onClickSave">保存</button>
            </p>
            </div>
        </div>

edit_flgという状態変数を見て、これがtrueならば、タグをinputに置き換える、という作りになっています。

では、データの方はというと、

        data() {
            return {
                error_message: "",
                error_flg:false,
                errors: {},

 中略

                nums: [
                    {text:'1', value:1},
                    {text:'2', value:2}
                ],
                timeList:[],
                selectRoom: 0,
                rooms: [],
                result: [],
                param: {
                    year: 2019,
                    month: 1,
                    room: 1
                },
                registers: [],
                showContent: false,
                contents: {
                    name: "",
                    address: "",
                    phone: "",
                    num: 0,
                    roomid: 0,
                    room: "",
                    days: 0,
                    start_day: "",
                    checkout: "",
                },
                edit_flg: false
            }
        },

ポイントはedit_flg。これをtrueにすることで、テンプレートが編集用に置き換わります。

なお、編集中のテンプレートは、予約追加時と同じくらいの機能を持たなくてはいけません。

もう、予約追加処理も、この中に入れてしまってもいいのかもしれない。

実際の処理は、

        created: function() {
            this.getRooms();
            this.getTimeList();
        },
        methods: {
            getRooms: function() {
                var self = this;
                axios.post('/api/rooms').then(function(response){
                    response.data.roomLists.forEach(element => {
                        self.rooms.push({id:element.id, name:element.name});
                    });
                }).catch(function(error){
                    console.log("失敗しました");
                });
            },
            getRegisters: function() {
                var self = this;
                this.param.year = this.selectYear;
                this.param.month = this.selectMonth;
                this.param.room = this.selectRoom;
                axios.post('/api/registers', this.param).then(function(response){
                    self.registers = [];
                    response.data.registerLists.forEach(element => {
                        self.registers.push(
                            {
                                id:element.id, 
                                name:element.name,
                                address:element.address,
                                phone:element.phone,
                                num:element.num,
                                roomid:element.roomid,
                                room:element.room,
                                days:element.days,
                                start_day:element.start_day, 
                                checkout:element.checkout
                            }
                        );
                    });
                }).catch(function(error){
                    console.log("失敗しました");
                });
            },
            onClickEdit: function(){
                this.edit_flg = true;
                var checkoutTime = this.contents.checkout.split(" ")[1];
                this.timeList.forEach(element => {
                    if(checkoutTime == element.value+":00"){
                        this.contents.checkout = element.key;
                    }
                });
            },
            onClickSave: function(){
                var self = this;
                this.param.year = this.selectYear;
                this.param.month = this.selectMonth;
                this.param.room = this.selectRoom;
                this.param.contents = this.contents;
                axios.post('/api/update', this.param).then(function(response){
                    self.registers = [];
                    response.data.registerLists.forEach(element => {
                        self.registers.push(
                            {
                                id:element.id, 
                                name:element.name,
                                address:element.address,
                                phone:element.phone,
                                num:element.num,
                                roomid:element.roomid,
                                room:element.room,
                                days:element.days,
                                start_day:element.start_day, 
                                checkout:element.checkout
                            }
                        );
                    });
                    self.closeModal();
                }).catch(function(error){
                    self.error_flg = true;
                    self.error_message = error.response.data.errors;
                });
            },
            openModal: function(id){
                for(var i = 0; i< this.registers.length; i++){
                    if(this.registers[i].id == id){
                        this.contents.id = this.registers[i].id;
                        this.contents.name = this.registers[i].name;
                        this.contents.address = this.registers[i].address;
                        this.contents.phone = this.registers[i].phone;
                        this.contents.num = this.registers[i].num;
                        this.contents.roomid = this.registers[i].roomid;
                        this.contents.room = this.registers[i].room;
                        this.contents.days = this.registers[i].days;
                        this.contents.start_day = this.registers[i].start_day;
                        this.contents.checkout = this.registers[i].checkout;
                        break;
                    }
                }
                this.showContent = true;
                this.edit_flg = false;
            },
            closeModal: function(){
                this.showContent = false;
                this.edit_flg = false;
            },
            getTimeList: function(){
                var self = this;
                axios.post('/api/timelist').then(function(response){
                    for (let [key, value] of Object.entries(response.data.timelist)){
                        self.timeList.push({key: key, value: value});
                    }
                }).catch(function(error){
                    console.log("失敗しました");
                });
            }

onClickEdit()で、詳細画面から、編集画面に切り替わります。

そして、onClickSave()で、入力したデータをLaravel側のAPI処理にデータを渡します。

うん、予約追加もこの中でいいよね。

あと、サーバ側でエラーが発生した場合のメッセージ表示も追加しています。

error_flgがtureになったらテンプレートにもその要素が表示され、API側で送られたメッセージが画面に表示されます。

では、API側の処理。

ルーティングに以下を追加します。

Route::post('/api/update', 'ApiController@update');
Route::post('/api/timelist', 'ApiController@timelist');

処理は、

    public function timelist(Request $request)
    {
        return response()->json(['timelist' => $this->registerManagement->getTimeList()]);
    }

    public function update(Request $request)
    {
        \Log::debug(print_r($request->contents, true));
        if($this->registerManagement->checkScheduleForUpdate($request->contents["start_day"], 
                                                            $request->contents["days"], 
                                                            $request->contents["id"], 
                                                            $request->contents["roomid"]) == false)
        {
            \Log::debug("スケジュールが重複しています");
            return response()->json([
                'errors' => "スケジュールが重複しています"
            ], 400);
        }
        $param = $this->registerManagement->getParam();
        $this->registerManagement->updateById($request->contents["id"],
        [
            $param[0] => $request->contents["name"],
            $param[1] => $request->contents["address"],
            $param[2] => $request->contents["phone"],
            $param[3] => $request->contents["num"],
            $param[4] => $request->contents["days"],
            $param[5] => $request->contents["start_day"],
            $param[6] => false,
            $param[7] => date('Y-m-d H:i', strtotime($request->contents["start_day"].' + '.$request->contents["days"].' day') + $request->contents["checkout"])
        ], $request->contents["roomid"]);
        return response()->json(['registerLists' => $this->registerManagement->getListByMonth(
            $request->year,
            $request->month,
            $request->room
        )]);
    }

timelist()というのは、データベースで処理するtick値と画面に表示する時刻のテーブルです。

これがあるためにつまずいた。

tick: “時刻(00:00)”

という形でデータを持っていたために、これがうまくVueで処理されないので、JavaScriptで形を変換したのですよ。

このやり方を見つけるのに苦労した・・・。

            getTimeList: function(){
                var self = this;
                axios.post('/api/timelist').then(function(response){
                    for (let [key, value] of Object.entries(response.data.timelist)){
                        self.timeList.push({key: key, value: value});
                    }
                }).catch(function(error){
                    console.log("失敗しました");
                });
            }

ここの処理ね、

[{tick: “時刻(00:00)”},{ },・・・]

このフォーマットを

[{key:tick, value:”時刻”},{ },・・・}

に変換したのですよ。

これを導き出すのに苦労しました。

でも、これができれば今までのサーバ側の処理が、ほぼ、そのまま使えるわけで、

編集画面でも、予約追加と同じことができるようになりました。

っていうか、追加処理もこの形にしよう。

ってなことで次回。