tohokuaikiのチラシの裏

技術的ネタとか。

Laravelのファイルアップロードのルートパス

config/filesystems.php に入っているので、

<?php
 config('filesystems.disks.public.root');

で取れる。

ちなみに、

<?php
 config('filesystems.disks.local.root');

はファイルアップロードではないstorageの場所。

ファイルをアップロードすると、というか$request->file('foo')->store()する際には、 config('filesystems.disks.public.root'); のpublicが付いてるっぽいので、後で取るといは、 config('filesystems.disks.local.root');から実ファイルパスを取ると良いのかな?

…ということは、この二つを後で返ると地獄が待っている。。。

まぁ、privateメソッドで外だししておくかな。

Laravelのデプロイ

自分用のメモ

Laravel自身

composerで関連パッケージをインストール

$ composer install

autoloadを作成する

$ composer dump-autoload

.envを作って、migrate

$ ./artisan migrate

Vue関連のファイルを出力

node_modulesをインストール

$ npm install

で、コンパイル

$ npm run production

こんだけ。

えー。めっちゃ簡単だった。artisan serveで開発してるからApacheのmod_phpよりfpmの方がいいのかもしれない。

php7.3-fpmはphp7.3のmysqlが入ってたけど、artisanはcliで動かして、/usr/bin/env php -vやったらphp7.4だったので

# apt install -y php7.4-mysql

してやらないと動作しなかった。気付かなかったな―。

VueのAjax通信の前後で共通のLoaderを入れる

ajaxの前後でLoading画面を出すやつです。

なんか、スゲー探してようやく見つけた…。
最初、Vuexを使わないようにしてたら全然できなくて、Vuexを使ったら30分でできて時間返してって感じだった。Vuexは恐れずに使え。

main.js

import Vue from 'vue';
import VueRouter from 'vue-router';
import Vuex from 'vuex'
import router from 'router';

window.Vue = require('vue');
Vue.use(VueRouter);
Vue.use(Vuex)

// loading状態を管理するためのVuex
const store = new Vuex.Store({
    state: {
        loadingCount: 0
    },
    mutations: {
        startLoader: (state) => {
            state.loadingCount++;
        },
        endLoader: (state) => {
            if (state.loadingCount > 0) {
                state.loadingCount--;
            }
        }
    }
});

// メインVue
const app = new Vue({
    el: '#app',
    router,
    store,
    components: {
        'my-vue-loading': MyVueLoading
    },
    computed: {
        loading() {
            return store.state.loadingCount > 0;
        }
    },
    created: function () {
        axios.interceptors.request.use(async config => {
            store.commit('startLoader');
            return config;
        });
        axios.interceptors.response.use(response => {
            store.commit('endLoader');
            return response;
        }, error => {
            store.commit('endLoader');
            throw error;
      });
    }
});

このcreatedに挟むのが分からんかった…

Loaderを使いたい時

router-viewを含むHTMLで

<div v-show="loading">Loading...</div>
<div v-show="!loading"><router-view></router-view></div>

な感じで。

Vuejsのコンポーネントを使ってsyncとかデータのやり取り

登録と編集って同じフォームを使いまわすので、Componentにしてあれこれできないかなと思ってたら、意外とデータを親子のVueでやり取りするのが面倒そうで…

を参考に。

上記の記事の問題点

なんで、子コンポーネントでまたpropsを定義し直さないと…というのが死ぬほど嫌だったので、考えた。ES2015を全然知らないのに考えた。

とりあえずこんなかんじ。

親側 Create.vue

<template>
    <div>
        <order-form
          v-bind.sync="order"
          ></order-form>
    </div>
</template>
<script>
import OrderFrom "@/components/OrderForm";
import defaultOrder from "@/helper/order";
export default {
    components: {
        'order-form': OrderForm,
    },
    data() {
        return {
            order: (new defaultOrder).props(),
        }
    }
}
</script>

子側 OrderForm.vue

<template>
    <div>
            <div class="form-group">
                <label>お名前</label>
                <input type="text" :value="name"
                       @input="$emit('update:name', $event.target.value)"
                       :class="{'form-control':true, 'error': false}">
            </div>
            <div class="form-group">
                <label>メールアドレス</label>
                <input type="text" :value="email"
                       @input="$emit('update:email', $event.target.value)"
                       :class="{'form-control':true, 'error':false}">
            </div>
            <div class="form-group">
                <label>電話番号</label>
                <input type="text" :value="tel"
                       @input="$emit('update:tel', $event.target.value)"
                       :class="{'form-control':true, 'error':false}">
            </div>
    </div>
</template>
<script>
import defaultOrder from "@/helper/order";
export default {
    props: (new defaultOrder()).defs,
    data() {
    },
};
</script>

Orderの定義ファイル

helper/order.js

export default class defaultOrder {
    constructor() {
        this.defs = {
          email: {
            type: String,
            default: ""
          },
          name: {
            type: String,
            default: ""
          },
          tel: {
            type: String,
            default: ""
          },
        };
    }
    
    props(){
        let prop = {};
        for (let p in this.defs){
            prop[p] = this.defs[p].default;
        }
        return prop;
    }
};

みたいな。

でもダメだね。

これ、Modelを一括で渡すには良いけど、他のプロパティが渡せない。 ダメだわ。普通に1個づつ渡すしか無いな。