作りたいものがありすぎる

40歳を過ぎてプログラミングを始めた人の顛末とこれからなど

基礎から学ぶVue.js CHAPTER2 データの登録と更新 読書メモ

今回は輪読担当ではありませんが、ひとまずメモをまとめたのでアップします。

以下の記事は2019/2/7 コワーキングスペース秋葉原Weeybleで行われる輪読会
[秋葉原] 基礎から学ぶVue.js輪読会 ch2 データの登録と更新(初心者歓迎!)のための読書メモとなります。
以下の書籍の CHAPTER2 Vue.jsとデータの登録と更新 のメモです。

基礎から学ぶ Vue.js

基礎から学ぶ Vue.js


CAPTER2

SECTION 07 基本データのバインディング

Mustache(マスタッシュ記法) hogeプロパティをhtmlにバインドする

<p>{{ hoge }}</p>

バインドは属性に使えない
下はエラー

<input type="text" value="{{ message }}">

これが正しい
属性へのバインドはv-bindディレクティブを使う

<input type="text" v-bind:value="message">
<!-- 省略して書くとこう -->
<input type="text" :value="message">

cssスタイルはキャメルケースで指定

<button v-on:click="isActive=!isActive">isActiveを切り替える</button>
<p v-bind:class="{ child: isChild, 'is-active': isActive }" class="item">
  動的なクラス
</p>
<p v-bind:style="{ color: textColor, backgroundColor: bgColor }" class="item">
  動的なスタイル
</p>
new Vue({
    el: '#app',
    data: {
        isChild: true,
        isActive: true,
        textColor: 'red',
        bgColor: 'lightgray'
    }
})
.item {
  padding: 4px 8px;
  transition: background-color 0.4s;
}
.is-active {
  background: #ffeaea;
}

オブジェクトデータで渡す方法
Vue.js側でひとまとめで定義

<p v-bind:class="classObject">Text</p>
<p v-bind:class="classObject_2">Text</p>
new Vue({
    el: '#app',
    data: {
        classObject: {
            isChild: true,
            isActive: true,
            textColor: 'red',
            bgColor: 'lightgray'
        },
        classObject_2: {
            isChild: true,
            isActive: true,
            textColor: 'red',
            bgColor: 'lightgray'
        }
    }
})

複数の属性のデータバインディング

沢山のプロパティがあっても

new Vue({
    el: '#app',
    data: {
        item: {
            id: 1,
            src: 'item1.jpg,
            alt: 'サムネ画像です',
            width: 200,
            height: 100,
        }
    }
})

まとめて定義できる

<img v-bind="item">

特定の要素のみに変更を加えることも可能

<img v-bind="item" v-bind:id="'thunb-' + item.id">
<!-- thunb-1 の id が付与される -->

SVGのデータバインディングベクター画像)

<div id="app">
  <svg xmlns="http://www.w3.org/2000/svg" version="1.1">
    <circle cx="100" cy="75" v-bind:r="radius" fill="lightpink" />
  </svg>
  <input type="range" min="0" max="100" v-model="radius">
</div>
new Vue({
    el: '#app',
    data: {
        radius: 50
    }
})

SECTION 09 テンプレートにおける条件分岐

v-if``v-showディレクディブは付与した要素の描画・表示に条件を適用する。

okプロパティがtrueの時のみdiv要素を表示する

<div v-if="ok">hoge</div>
<div v-show="ok">hoge</div>
new Vue({
    el: '#app',
    data: {
        ok: false
    }
})

条件を満たさない場合に生成されるhtml display:none となる

<div style="display: none;">hoge</div>

v-if と v-show の違いと使い分け

v-if の場合

DOMレベルでない事になる

v-show の場合

display:none が付与される
切り替え頻度が高いならこっちが処理早い

タグによるv-if グループ化

複数の要素を if で切り替えたい場合グループ化できる

<tamplate>
    <header>title</header>
    <div><contents/div>
</tamplate>

v-else-if 及び v-else によるグループ化

<div v-if="type === 'A'">AAA</div>
<div v-else-if="type === 'B'">BBB</div>
<div v-else>どちらでも無い場合</div>

v-else-if v-else key

keyを設定して属性の重複による発動しない状態を回避する

<!-- 2つのdivが違う要素である事を明示的にする -->
<div v-if="loaded" key="content-visible">
  content
</div>
<div v-else key="content-loading">
  loading now...
</div>

SECTIOM 10 リストデータの表示と更新

要素を繰り返して描画する

みたまんま、こんな感じで繰り返し描画できる。
v-for="item in list"php や JS のfor 文や foreach と同じ様に使える

  <ul>
    <li v-for="item in list" v-bind:key="item.id">
      ID.{{ item.id }} {{ item.name }} HP.{{ item.hp }}
    </li>
  </ul>
new Vue({
    el: '#app',
    data: {
        list: [
            { id: 1, name: 'スライム', hp: 100 },
            { id: 2, name: 'ゴブリン', hp: 200 },
            { id: 3, name: 'ドラゴン', hp: 500 }
        ]
    }
})

出力結果

<ul>
    <li>ID.1 スライム HP.100</li>
    <li>ID.2 ゴブリン HP.200</li>
    <li>ID.3 ドラゴン HP.500</li>
</ul>

インデックスとオブジェクトキーの使用

変数部分をカッコで囲んで配列インデックスを任意に受け取れる

<li v-for="(item, index ) in list"> ...</li>

オブジェクトなら「値」「キー」「インデックス」の順で任意に受け取れる

<li v-for="(item, key, index ) in list"> ...</li>

キーの役割

これ大事! v-bind:key="item.id"

<li v-for="item in list" v-bind:key="item.id">

要素にユニークなキー属性を追加するのが望ましい。ほぼ必須と考えて良い。
キーが無いと要素全部の更新が入る。なのでSQLidを入れる位に考えると良い。

繰り返し描画しながら様々な条件を適用する

v-if を絡めて、比較演算子で条件付けて、特定条件での表示などもできる。

  <ul>
    <li v-for="item in list" v-bind:key="item.id" v-bind:class="{ tuyoi: item.hp > 300 }">
      ID.{{ item.id }} {{ item.name }} HP.{{ item.hp }}
      <span v-if="item.hp > 300">つよい!</span>
    </li>
  </ul>

出力結果

<ul>
    <li>ID.1 スライム HP.100</li>
    <li>ID.2 ゴブリン HP.200</li>
    <li>ID.3 ドラゴン HP.500<span>つよい!</span></li>
</ul>

リストの更新

注意点として以下のケースで更新を検知できない

  1. インデックス数値を使った配列要素の更新
  2. 後から追加されたプロパティの更新

リストに要素を追加

push,unshiftを使う

this.list.push(要素)

以下、サンプル、ボタン押下でフォーム内の名前のモンスターがリストに追加される。IDは自動生成。HPは500固定

  <!-- このフォームの入力値を新しいモンスターの名前に使う -->
  名前
  <input v-model="name">
  <button v-on:click="doAdd">モンスターを追加</button>
  <ul>
    <li v-for="item in list" v-bind:key="item.id">
      ID.{{ item.id }} {{ item.name }} HP.{{ item.hp }}
    </li>
  </ul>
new Vue({
    el: '#app',
    data: {
        name: 'キマイラ',
        list: [
            { id: 1, name: 'スライム', hp: 100 },
            { id: 2, name: 'ゴブリン', hp: 200 },
            { id: 3, name: 'ドラゴン', hp: 500 }
        ]
    },
    methods: {
        // 追加ボタンをクリックしたときのハンドラ
        doAdd: function () {
            // リスト内で1番大きいIDを取得
            var max = this.list.reduce(function (a, b) {
                return a > b.id ? a : b.id
            }, 0)
            // 新しいモンスターをリストに追加
            this.list.push({
                id: max + 1, // 現在の最大のIDに+1してユニークなIDを作成
                name: this.name, // 現在のフォームの入力値
                hp: 500
            })
        }
    }
})

リストから削除する

リストからの削除は配列メソッドのspliceを使う

li毎に削除ボタンが表示され、クリックで対象を消せる

  <ul>
    <li v-for="(item, index) in list" v-bind:key="item.id">
      ID.{{ item.id }} {{ item.name }} HP.{{ item.hp }}
      <!-- 削除ボタンをv-for内に作成 -->
      <button v-on:click="doRemove(index)">モンスターを削除</button>
    </li>
  </ul>
new Vue({
    el: '#app',
    data: {
        list: [
            { id: 1, name: 'スライム', hp: 100 },
            { id: 2, name: 'ゴブリン', hp: 200 },
            { id: 3, name: 'ドラゴン', hp: 500 }
        ]
    },
    methods: {
        // 要素を削除ボタンをクリックしたときのハンドラ
        doRemove: function (index) {
            // 受け取ったインデックスの位置から1個要素を削除
            this.list.splice(index, 1)
        }
    }
})

リスト要素( <li>hoge</li> )に関しては以下の様な配列メソッドを使用して操作が可能

  • push
  • pop
  • shift
  • unshift
  • splice
  • sort
  • reverse

これは駄目

this.list[0] = { id: 1, name: 'hoge', hp: 500 }

これなら大丈夫

Vue.setメソッドを使用して明示的に更新できる。エイリアスthis.$setとなる

this.$set(更新するデータ , インデックスorキー , { 新しい値 })

上記からの具体例だとこんな感じ

this.$set(this.list, 0, { id: 1, name: 'hoge', hp: 500 })

プロパティを追加する

this.$setメソッドは持ってないプロパティをリアクティブデータとして追加するために使用できる。

new Vue({
    el: '#app',
    data: {
        list: [
            { id: 1, name: 'スライム', hp: 100 },
            { id: 2, name: 'ゴブリン', hp: 200 },
            { id: 3, name: 'ドラゴン', hp: 500 }
        ]
    },
    created: function() {
        // すべての要素にactiveプロパティを追加したい
        this.list.forEach(function(item) {
            this.$set(item, 'active', false)
            // 「item.active = false」ではリアクティブにならない
        }, this)
    }
})

リスト要素プロパティを更新する

プロパティ hp を更新する 作例

  <ul>
      <li v-for="(item, index) in list" v-bind:key="item.id" v-if="item.hp">
          ID.{{ item.id }} {{ item.name }} HP.{{ item.hp }}
      <span v-if="item.hp < 50">瀕死!</span>
      <!-- ボタンはv-for内に作成 -->
      <button v-on:click="doAttack(index)">攻撃する</button>
    </li>
  </ul>

liの最後にあるv-if="item.hp"は hpが0になると消える処理になる。
<span v-if="item.hp < 50">瀕死!</span>は hp 50未満で表示される。

new Vue({
    el: '#app',
    data: {
        list: [
            { id: 1, name: 'スライム', hp: 100 },
            { id: 2, name: 'ゴブリン', hp: 200 },
            { id: 3, name: 'ドラゴン', hp: 500 }
        ]
    },
    methods: {
        // 攻撃ボタンをクリックしたときのハンドラ
        doAttack: function (index) {
            this.list[index].hp -= 10 // HPを減らす
        }
    }
})

ユニークキーを持たない配列

出来ない訳ではない、簡易にする際はこれでもOK

<option v-for="item in list">{{ item }}</option>
data: {
    list: ['aaa', 'bbb', 'ccc']
}

オプションにデータを持たないv-for

v-forに数値をセットすると以下の例の様にspanで囲まれた1~15の値を出力できる

<span v-for="item in 15">{{ item }}</span>

同様に 1,5,10,15 の4つを出力する

<span v-for="item in [1, 5, 10, 15]">{{ item }}</span>

文字列に対するv-for

文字列にv-for を使うと1文字ずつ別々の要素で描画される

<span v-for="item in text">{{ item }}</span>
new Vue({
    el: '#app',
    data: {
        text: 'hoge'
    }
})

出力結果

<span>h</span>
<span>o</span>
<span>g</span>
<span>e</span>

これを利用するとテキストアニメーションが作れるらしい

外部からデータを取得する

外部データはJSONやWebAPIで取得する必要がある。
JSONを外部データから取り込んでみる。
htmlの下の方にある<script>内に javascriptライブラリのaxiosCDNを読み込む1行を追加する。

  <script src="https://cdn.jsdelivr.net/npm/axios@0.17.1/dist/axios.min.js"></script>

これでAJAXが使える様になる

  <ul>
    <li v-for="(item, index) in list" v-bind:key="item.id">
      ID.{{ item.id }} {{ item.name }} HP.{{ item.hp }}
    </li>
  </ul>
new Vue({
    el: '#app',
    data: {
        // あらかじめ空リストを用意しておく
        list: []
    },
    created: function () {
        axios.get('list.json').then(function (response) {
            // 取得完了したらlistリストに代入
            this.list = response.data
        }.bind(this)).catch(function (e) {
            console.error(e)
        })
    }
})

ライフサイクルフックの created を使って new 直後にjsonを非同期で取り込む、取り込む前は data.list の空配列[]が一瞬だが、適用されている。ここが表示されるまでに、ローディングアニメーション処理とか入るとカッコよくなる。

JSONファイル list.json

[
  { "id": 1, "name": "スライム", "hp": 100 },
  { "id": 2, "name": "ゴブリン", "hp": 200 },
  { "id": 3, "name": "ドラゴン", "hp": 500 }
]

SECTION 11 DOMを直接参照する $el と $refs

DOMにアクセスするには、インスタンスプロパティ$el,$refsを使用する。
但し、ライフサイクルフックのmounted以降でないと使えない

$el の使い方

テンプレートを囲んでいるルート要素は$el を使って参照できる。
例えば<canvas>要素などにアクセスしたい時などに使用する。

var app = new Vue({
  el: '#app'
      mounted: function() {
      console.log(this.$el)  // <div id="app"></div>
  }
})

$refsの使い方

<div id="app">
    <p ref="hello">hello</p>
    <!--  p要素にhelloと名を付けた   -->
</div>

以下の様にアクセス

new Vue({
    el: '#app',
      mounted: function() {
      console.log(this.$refs.hello)  // p要素のDOMとなる
    }
})

$el や$refsは一時的な変更です!

これらは仮想DOMではないので描画処理の最適化をしない
操作の都度描画するので注意

<div id="app">
  <button v-on:click="handleClick">カウントアップ</button>
  <button v-on:click="show=!show">表示/非表示</button>
  <span ref="count" v-if="show">0</span>
</div>
new Vue({
  el: '#app',
  data: {
    show: true
  },
  methods: {
    handleClick() {
      var count = this.$refs.count
      if (count) {
        count.innerText = parseInt(count.innerText, 10) + 1
      }
    }
  }
})

カウントアップに対して、表示・非表示ボタンがあるが、count up した状態で、非表示・再表示すると、カウントが0にもどってしまう。これは、DOMに対して加算をしたのみなので、DOMが消えると、値も消えてしまうため。 vue.js での指定なら仮想DOMなのでこうはならない。

SECTION12 テンプレート制御ディレクティブ

ディレクティブ 作用
v-pre テンプレートのコンパイルをスキップする XSS対策に有効
v-once 一度だけバインディングを行う
v-text Mustash {{ }} の代わりにテキストコンテンツを描画
v-html HTMLタグをそのまま描画する
v-cloak インスタンスの準備が終わると取り除かれる

v-pre

XSS対策などで使う

<a v-bind:href="#" v-pre>
    hello {{ message }}
</a>

<!-- これは以下のよう生だし描画される -->
<a v-bind:href="#" v-pre> hello {{ message }}</a>

v-once

描画されたあとに 指定したプロパティの値が変わってもDOMは更新されない

v-text

Mustash {{ kore }} を使わないで書くパターンがある場合に使える

var app = new Vue({
  el: '#app'
      data: {
          message: 'Hello!'
  }
})

こんな風にmessageでバインドできる。

<span v-text="message"></span>

v-html

v-pre (XSS対策)とは逆に、htmlのタグ等、をそのまま出してしまう奴
自分がコントロールできない外部やユーザー要因のデータ部分に使うと脆弱性ありありなので使い所には注意が必要。

var app = new Vue({
  el: '#app'
      data: {
          message: 'hello<strong>Vue.js!</strong>'
  }
})

こんな風にhtmlがそのまま出力する事ができる。

<span v-html="message"></span>
<!-- これは以下のよう描画される -->
<span>hello<strong>Vue.js!</strong></span>

v-cloak

インスタンスの準備ができると自動的に取り除かれる。コンパイル前のテンプレートが表示されるのを防げる

CSSに以下の様なスタイル定義をする

[v-cloak] { display: none}

以下のやつで画面読み込み時に#app要素を隠せる。
インスタンス生成でv-cloak属性が外れてフェードイン表示される。

@keyframes cloak-in {
  0% {
    opacity: 0;
  }
}
#app {
  animation: cloak-in 1s;
}
#app[v-cloak] {
  opacity: 0;
}

仮想DOMとは?

超要約するとDOMツリーの上にもう一枚仮想DOMのツリーを作ってVue.jsでは基本的に仮想側の操作をする。 DOM自体が変わったり、変えたりした際は非同期で本来のDOMを変更しているので、タイムラグや、DOMの入れ替え時に反映されない事がある。
例えば v-if,v-elseで分岐表示させた際等にこれが起こりうる。そのため、分岐の各要素に異なる key を付けて別物ということを認識させる事でちゃんと描画されるようになる。

jQuery などのDOMライブラリとの併用

も、一応可能だが、Vue.jsがDOMを直接いじる $el,$refsが同様の事ができるので、併用はできるけど、まあ、無意味化しつつあるよね。ということらしい。

まとめ

  • 使用したいデータはdataオプションに登録しよう
  • 操作するリストには不変でユニークなkey属性を設定しよう
  • 配列インデックスを使った更新はVue.setを使う
  • 関数の呼び出し方ではthisは変化することがある
  • $elと$refsはmounted以降で使う

Laravelのブラウザテストでテストメソッド毎にシーディングを毎回しない方法

前置き

アプリをある程度作り込んでから、自動テストやTDD(テスト駆動開発)を覚え、いざ自分のアプリで実践しようとした所、かなり手を入れないとろくなユニットテストができない状態という事が分りました。
なにしろユーザーのロール権限が5つもあり、権限毎に表示や動作が異なる箇所が多々ある。(どうしてこうなった)
メソッドの中で他のメソッドを呼びまくり、値を拾っては他に投げ、みたいな入出力の制御が複雑で大変危うい処理もある。
また、例えばあちらのバグをつぶすと、こちらでバグになる。とか、この権限での仕様を変えたけど、他の権限での動作や表示には対応してる?といった確認作業も多くなりました。

で、やむなく現在のアプリを自動ブラウザテストでそれぞれの権限での表示や動作を検証する、という事をしてます。要は自分で画面見て、操作して、というのを機械にやらせる処理を淡々と書く作業です。(正直しんどい)

本題

で、その際によくあるのが setUp() メソッド(テストのメソッド毎に実行される処理)に、シーディング処理を書く奴、こんなのです。

<?php

namespace Tests\Browser;
// use 省略
class Profile_superAdmin_user_Test extends DuskTestCase
{

    use RefreshDatabase;

    protected function setUp()
    {
        parent::setUp();
        Artisan::call('migrate:refresh');
        Artisan::call('db:seed');
    }
    // 以下略
}

この処理なんですが、setUp()はこの下に書かれるブラウザテストの複数のメソッド実行前に毎回実施されます。なので、DBの再構成をテストメソッド毎に毎回やると、テスト実施に結構時間がかかってしまいます。

なので、この中の処理をテストクラスの最初の1回のみ実施される、 setUpBeforeClass()を書いたのですが、理由は忘れましたがうまく行きませんでした。(BrowserテストにsetUpBeforeClass()が無かったか? Artisanコマンドが使えなかった?だったと思います。)

では上手い方法はないか?と調べた所、以下のページの記述に当たりました。

How Do I Seed My Database in the setupBeforeClass Method in a Laravel 4 Unit Test?

日本語直訳サイト
Laravel 4ユニットテストでsetupBeforeClassメソッドにデータベースをシードするにはどうすればよいですか?

<?php

namespace Tests\Browser;
// use 略

class Admin_Community_superAdmin_user_Test extends DuskTestCase
{
    protected static $db_inited = false;
    use RefreshDatabase;

    protected static function initDB()
    {
        Artisan::call('migrate:refresh');
        Artisan::call('db:seed');
    } 

    protected function setUp()
    {
        parent::setUp();
        if (!static::$db_inited) {
            static::$db_inited = true;
            static::initDB();
        }
    }
    // 略
}

setUp() メソッドをあたかもsetUpBeforeClass()の様にクラスインスタンス後に1度だけやってくれる書き方です。
$db_initedという静的プロパティを持たせてsetUp()で一度 true にしてしまったら、 setUp()内の ifの処理で以降は Artisanファサードを呼ばない。という実装。ピタゴラスイッチ的な動きですよね。こういうのって見ればそれなりに動き追えますが、自分で書ける気がしません。が、なにはともあれ解決。

しかしこれだと、テストクラス内でDBの値を変更してしまう処理を書くと、以降のテストに影響がでてしまうのですが、そこは、テストクラスを上手く分けて書いて行けば解決できそうです。

追記

その後以下の様にテストメソッド内に Artisanファサードを使ってDBのシーディングを行う処理を書くことで、さらに必要な時にだけ、シーディングが行えることがわかりました。このまま行くとsetUp()メソッドが無くても何とかなるる感じですね。

<?php

    /**
     * @test
     */
    public function DBを編集するテスト()
    {
        // 省略
    }

    /**
     * @test
     */
    public function 後処理()
    {
        $this->browse(function ($browser) {
            $browser->visit('/user/edit?id=1')
               // assert が書かれて無いとテスト完了時に警告が出る為、便宜上入れた assert
                ->assertSeeIn('.comp-title', 'プロフィール編集');
                echo 'now seeding!';
                Artisan::call('migrate:refresh');
                Artisan::call('db:seed');
        });
    } 

Let's Encrypt のTLS-SNI-01から http-01 方式への変更をした備忘録

無料で使えるSSL認証Let's Encrypt から以下の様なメールが来ました。

Action required: Let's Encrypt certificate renewals

Hello,

Action may be required to prevent your Let's Encrypt certificate renewals
from breaking.

If you already received a similar e-mail, this one contains updated
information.

Your Let's Encrypt client used ACME TLS-SNI-01 domain validation to issue
a certificate in the past 60 days. Below is a list of names and IP
addresses validated (max of one per account):

 www.livelynk.jp (160.16.207.76) on 2018-12-25

TLS-SNI-01 validation is reaching end-of-life. It will stop working
temporarily on February 13th, 2019, and permanently on March 13th, 2019.
Any certificates issued before then will continue to work for 90 days
after their issuance date.

You need to update your ACME client to use an alternative validation
method (HTTP-01, DNS-01 or TLS-ALPN-01) before this date or your
certificate renewals will break and existing certificates will start to
expire.

Our staging environment already has TLS-SNI-01 disabled, so if you'd like
to test whether your system will work after February 13, you can run
against staging: https://letsencrypt.org/docs/staging-environment/

If you're a Certbot user, you can find more information here:
https://community.letsencrypt.org/t/how-to-stop-using-tls-sni-01-with-certbot/83210

Our forum has many threads on this topic. Please search to see if your
question has been answered, then open a new thread if it has not:
https://community.letsencrypt.org/

For more information about the TLS-SNI-01 end-of-life please see our API
announcement:
https://community.letsencrypt.org/t/february-13-2019-end-of-life-for-all-tls-sni-01-validation-support/74209

Thank you,
Let's Encrypt Staff

Google翻訳にかけてみる

必要なアクション:証明書の更新を暗号化しましょう

こんにちは、

あなたのLet's Encrypt証明書の更新
が壊れないようにするための行動が必要かもしれません。

すでに同じようなEメールを受け取っている場合は、これには更新された
情報が含まれています。

Let's Encryptクライアント
が過去60日間に証明書を発行するためにACME TLS-SNI-01ドメイン検証を使用しました。以下は
検証された名前とIP アドレスのリストです(アカウントごとに最大1つ):2018-12-25の

 www.livelynk.jp(160.16.207.76)

TLS-SNI-01検証は廃止予定です。それは動作を停止します
2月13日、2019年に一時的に、かつ永久月13日に、2019年
それ以前に発行された証明書は90日間働き続ける
彼らの発行日後。


この日までに ACMEクライアントを更新して別の検証方法(HTTP-01、DNS-01、またはTLS-ALPN-01)を使用する必要があります。そうしないと
証明書の更新が中断され、既存の証明書の
有効期限が切れます。

私たちのステージング環境は、すでにあなたが好きなので、もし、TLS-SNI-01無効になってい
2月13日後にシステムが動作するかどうかをテストするために、あなたが実行することができます
ステージングに対して:https://letsencrypt.org/docs/s taging環境/

あなたがCertbotユーザーであるならば、あなたはここでより多くの情報を見つけることができます:
https://community.letsencrypt。org / t /どうやってtls-snを使うのかi-01-with-certbot / 83210

このフォーラムにはたくさんのスレッドがあります。あなたのかどうかを確認するために検索してください
質問が答えられたら、新しいスレッドを開いてください(
https://community.letsencrypt)。org /

TLS-SNI-01のサポート終了についての詳細は、当社のAPI 
発表
https://community.letsencryptをご覧ください。org / t / 2月13日 - 1919年 - すべてのtls-sni-01- validation-support / 74209

ありがとう、
スタッフを暗号化しましょう

とのことで、従来の検証方法TLS-SNI-01から HTTP-01、DNS-01、またはTLS-ALPN-01 へのいずれかへの変更が必要とのことで、ググって対応しました。

結論から言うと、先人方が既に変更方法を確立されており、同様の方法で事が済みましたが、参考にさせていただいたサイトのリンクと、その方法を張り付けておきます。
サーバー環境はさくらVPSのcentos7となります。

Let’s encryptのドメイン認証の方法をHTTP-01に変更するための準備で試行錯誤した件。
Let’s Encryptの更新エラーを直す(certbot renew失敗)
Let’s EncryptのTLS-SNI-01認証のバリデーションに伴う対応策まとめ

まず サーバーにログインして rootになって Let's Encryptを更新します。

# yum update certbot*

次に以下のサイトを参考に設定変更のコマンドを叩きました

Let’s encryptのドメイン認証の方法をHTTP-01に変更するための準備で試行錯誤した件。

# certbot renew –dry-run –preferred-challenges http-01,dns-01

ところが何やらエラーが

Traceback (most recent call last):
  File "/bin/certbot", line 5, in <module>
    from pkg_resources import load_entry_point
  File "/usr/lib/python2.7/site-packages/pkg_resources.py", line 3011, in <module>
    parse_requirements(__requires__), Environment()
  File "/usr/lib/python2.7/site-packages/pkg_resources.py", line 626, in resolve
    raise DistributionNotFound(req)
pkg_resources.DistributionNotFound: acme>=0.29.0

なんかよくわかりませんが、大事な事は最初か最後に書いてあるので、今回は最後の1行でググると以下のサイトの情報に行き当たりました。 Let’s Encryptの更新エラーを直す(certbot renew失敗)

同じエラーが載ってるのでドンピシャです。 手順も全く同じ経緯で原因の特定と解決ができました。

# yum search acme
読み込んだプラグイン:fastestmirror, langpacks
Loading mirror speeds from cached hostfile
 * base: ftp.iij.ad.jp
 * epel: mirrors.aliyun.com
 * extras: ftp.iij.ad.jp
 * remi-safe: ftp.riken.jp
 * updates: ftp.iij.ad.jp
====================================================== N/S matched: acme ======================================================
acme-tiny-core.noarch : core python module of acme-tiny
python2-acme.noarch : Python library for the ACME protocol
acme-tiny.noarch : Tiny auditable script to issue, renew Let's Encrypt certificates
dehydrated.noarch : A client for signing certificates with an ACME server

  Name and summary matches only, use "search all" for everything.

python2-acme.noarch の更新が必要とのことで、epelからupdate

# yum --enablerepo=epel update python2-acme

依存性解決をしてアップデートができました。

再度以下のサイトを参考に本来の目的である、Let's Encrypt のTLS-SNI-01から http-01 方式への変更を行います。
Let’s EncryptのTLS-SNI-01認証のバリデーションに伴う対応策まとめ

本当に最新か確認

# certbot --version
certbot 0.29.1

現時点でリンク先のバージョンと同じなので、まず大丈夫でしょう。 そして

新しいバージョンの場合は自動的にHTTP-01の認証が実行されるようです。 とありますが、一応リンク先同様、 -dry-run オプションで更新テストをしてみます。

# certbot renew --dry-run --preferred-challenges http

出力内容

Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/www.livelynk.jp.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cert not due for renewal, but simulating renewal for dry run
Plugins selected: Authenticator apache, Installer apache
Starting new HTTPS connection (1): acme-staging-v02.api.letsencrypt.org
Renewing an existing certificate
Performing the following challenges:
http-01 challenge for www.livelynk.jp
Waiting for verification...
Cleaning up challenges
Resetting dropped connection: acme-staging-v02.api.letsencrypt.org

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
new certificate deployed with reload of apache server; fullchain is
/etc/letsencrypt/live/www.livelynk.jp/fullchain.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
** DRY RUN: simulating 'certbot renew' close to cert expiry
**          (The test certificates below have not been saved.)

Congratulations, all renewals succeeded. The following certs have been renewed:
  /etc/letsencrypt/live/www.livelynk.jp/fullchain.pem (success)
** DRY RUN: simulating 'certbot renew' close to cert expiry
**          (The test certificates above have not been saved.)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

IMPORTANT NOTES:
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
   making regular backups of this folder is ideal.

Performing the following challenges:

http-01 challenge for www.livelynk.jp

//中略

Congratulations, all renewals succeeded. The following certs have been renewed:

翻訳:おめでとうございます、すべての更新は成功しました。以下の証明書が更新されました。

という訳で無事完了。普段サーバーの設定関連は散々ググって悩んで解決するのですが、今回は皆が同じ対応を迫られている時期だったこともあり、とても簡単に問題が解決できました。良かった。

【輪読会資料】基礎から学ぶVue.js CHAPTER1 Vue.jsとフレームワークの基礎知識 読書メモ

以下の記事は2019/1/31 コワーキングスペース秋葉原Weeybleで行われる輪読会
[秋葉原] 基礎から学ぶVue.js輪読会 #初回 ch1 フレームワークの基礎知識(初心者歓迎!) のための読書メモとなります。
以下の書籍の CHAPTER1 Vue.jsとフレームワークの基礎知識 のメモです。

基礎から学ぶ Vue.js

基礎から学ぶ Vue.js

目次

  • CHAPTER 1 Vue.jsとフレームワークの基礎知識
    • 01 Vue.jsについて
    • 02 Vue.jsのキーコンセプト
    • 03 豊富なリソースを活用しよう
    • 04 Vue.jsのインストール
    • 05 Vue.jsの基本機能
    • 06 オプションの構成を見てみよう
    • まとめ

はじめに

書籍の為のがっつりしたサイトがあります!必見!!なんて手厚いサポート体制なんでしょう!
基礎から学ぶ Vue.js

書籍内のコードはまずここを参考にすると良いでしょう
基礎から学ぶ Vue.js コード&動作メモ

CHAPTER 1 Vue.jsとフレームワークの基礎知識

01 Vue.jsについて

Laravelのフロントエンドで採用されて今人気!色々アツい!
jQuery的な手軽さがあり、学習コストが低い
日本語ドキュメントが充実
フレームワークとの相性が良い

02 Vue.jsのキーコンセプト

データ駆動のしくみ
× DOMが存在してそれを読み込んで操作
○ 最初にデータが存在、そのデータに適したDOMを構築する

テンプレートを使う

<div v-if="show">Hello Vue.js</div>

v-ifは仮想DOMをつくるテンプレートの記法

<body>
    <div id="app"></div><!-- ここに配置できる -->
</body>

#app配置する要素とアプリケーションを紐づけることをmountと呼ぶ

データバインディング

データと描画を同期させる仕組み
生JSだと色々面倒だし管理も大変だけどVue.jsなら簡単

DOMの更新はフレームワークに任せよう

それを解決するのがデータでバインディング型のライブライリ、やフレームワーク
Vue.jsもデータでバインディングの多くの機能を持つHTMLを扱う感覚で機能を使用できる

v- からはじまるディレクティブ

htmlの属性にv-if,v-bind,key,等で始まるやつをディレクティブといい、データディバイングを行うために使われる。

<div key="id"></div><!-- 1 -->
<div v-bind:key="id"></div><!-- 2 -->

1,は単純に[id]という文字列を表す
2,はv-で始まるディレクティブJSの変数idで、正確にはアプリに登録されたidというプロパティになる
例外はあるがひとまず、v-で始まってなければ単なる文字列と考えて良い

コンポーネント指向の画面構成

1ファイルの中に例えば部品であるheader,main,footer毎のファイルを作る。その個別のファイル毎にHTML,CSS,JS を書いて管理する。
1ファイルの中にHTML,CSS,JS を書いて管理することもある。
さらに従来のcssの使い方としてポピュラーな方法である、共有コードを別ファイルまとめて書くこともできる。

コンポーネントが増えても大丈夫

コンポーネントはVue.jsのもっとも強力な機能
コンポーネントのネスト化、構造化が容易
複雑な構造化が必要な場合は以下の拡張機能等を導入するとよい

静的サイトジェネレート機能のあるVue.jsの拡張フレームワーク

  • Nuxt.js (Weeybleさんで輪読会やるらしいです)
  • VuePress

03 豊富なリソースを活用しよう

jQueryやBootstlapを使わずとも、Vue.jsに最適化されたコンポ―ネントUIがWebにたくさんあるらしい

Vue.jsと相性のいいライブラリ

代表的なコンポーネント

04 Vue.jsのインストール

  • この本の6章まではスタンドアローン版の「Vue.js」ファイルを使う
  • 開発モードで使う(非minファイルという)
  • 本番環境では「vue.min.js」に置き換えた最適化ファイルを使う

ダウンロード版もありますが、手っ取り早くCDN(コンテンツデリバリーネットワーク  htmlのheadタグ内にscriptとして読み込む1行を書く)の方が良いと思います。

ダウンロードの場合
Vue.js GET STANDARD > インストール(左メニュー) > 開発バージョン(ボタン)

CDNの場合 下記いずれかを使用htmlのheadに記述する。
学習では当然開発バージョン

<!-- 開発バージョン、便利なコンソールの警告が含まれています -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<!-- 本番バージョン、サイズと速度のために最適化されています -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>

学習用のひな形ファイルを作る index.html

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>Vue.js App</title>
  <link href="main.css" rel="stylesheet">
</head>
<body>
  <div id="app">
    <!-- この#appの内側に色々なサンプルを書き込んでいく -->
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
  <script src="main.js"></script>
</body>
</html>

main.js

var app = new Vue({
  el: '#app'
})

これで適当なフォルダに保存したhtmlファイルをブラウザで開き、開発用コンソールを立ち上げる
chromeなら ctrl + shift + I

本にはないがcssも作った方が良い
main.css

body {
   /* ひとまず適当に書いて反映を確認してみる */
    color: blue;
}

さらにブラウザがchromeならこのような開発用の拡張機能をインストールすると便利そう
(但しlocalサーバー環境で無いと起動しない様です)
Vue.js devtools

05 Vue.jsの基本機能

htmlがわかる人なら簡単に扱えるそうです。

index.html 抜粋

  <div id="app">
    <p>{{ message }}</p><!-- ここに一行追加 -->
  </div>

main.js

var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue.js!'
  }
})

これでブラウザの画面にはHello Vue.js!が出力される

開発タブの Consoleに以下を入力すると…

console.log(app.message);

Hello Vue.js!と出力される

繰り返しの描画

一覧要素はdataオプションに登録され、そこに入れる配列やオブジェクトからv-forディレクティブで描画できる。

index.html

<ol>
  <li v-for="item in list">{{ item }}</li>
</ol>

main.js

var app = new Vue({
  el: '#app',
  data: {
    list: ['りんご', 'ばなな', 'いちご']
  }
})

開発用コンソールにapp.list.push('おれんじ')と入力すると、要素が追加できる。

1.りんご   
2.ばなな   
3.いちご   
4.おれんじ   

イベントの利用

クリックや選択要素が変わった際などのDOMイベントはv-onディレクティブを使う。
詳細はCHAPTER3
クリックするとhandleClickメソッドが呼ばれる例

index.html

<button v-on:click="handleClick">Click</button>

main.js

var app = new Vue({
  el: '#app',
  methods: {
    handleClick: function (event) {
      alert(event.target) // [object HTMLButtonElement]
    }
  }
})

ボタンが表示されクリックでalertがポップアップされるようになる

フォーム入力との同期

v-modelディレクティブを使用する
入力や選択で即時DOMに変更が反映される
詳細はCHAPTER3

index.html

<p>{{ message }}</p>
<input v-model="message">

main.js

var app = new Vue({
  el: '#app',
  data: {
    message: '初期メッセージ'
  }
})

フォームに入力した内容を編集するとmessage 部分に即反映されるのが確認できる

条件分岐

v-ifディレクティブを使用
詳細はCHAPTER2

index.html

<button v-on:click="show=!show">切り替え</button>
<p v-if="show">Hello Vue.js!</p>

main.js

var app = new Vue({
  el: '#app',
  data: {
    show: true
  }
})

showプロパティがtrueの際だけ<p>要素を出力する
コンソールにapp.show=false,app.show=trueと入力することでも表示の切り替えが出来る

トランジション&アニメーション

組み込みコンポーネント<transition>タグを使うと、CSSトランジションやアニメーションが使える
詳細はCHAPTER6

index.html

<button v-on:click="show=!show">切り替え</button>
<transition>
  <p v-if="show">Hello Vue.js!</p>
</transition>

main.js

var app = new Vue({
  el: '#app',
  data: {
    show: true
  }
})

main.css

.v-enter-active, .v-leave-active {
  transition: opacity 1s;
}
/* opacity:0から1へのフェードイン&フェードアウト */
.v-enter, .v-leave-to {
  opacity: 0;
}

ボタンを押す際にフェードアウト、フェードインでの表示切替アニメーション効果が適用される。

06 オプションの構成を見てみよう

基本的なオプションの構成

だいたいこんな感じらしいです。

var app = new Vue({

    // mountする要素
    el: '#app',
    // アプリケーションを紐づける要素のセレクタ

    // アプリケーションで使用するデータ
    data: {
        show: true
    }
    // `data`はアプリで使用するデータ、配列、オブジェクトが登録可能

    // 算出プロパティ
    computed: {
      computedMessage: function () {
        return this.message + '!'
      }
    }
    // `computed`関数によって算出されたデータ ここで処理した結果を返せる

    // ライフサイクルフック
    created: function () {  // created はすぐ実施される処理、他にも予約語がある。
      // 行いたい処理
    },
    // あらかじめ登録した処理を自動呼出しする`フック`と呼ばれる割り込み処理

    // アプリケーションで使用するメソッド
    methods: {
      myMethod: function () {
        // 行いたい処理
      }
    }
    // 処理の分割、細かな実装等で使う

})

created - ライフサイクルフック

あらかじめ登録した処理を自動呼出しするフックと呼ばれる割り込み処理が予約語でいくつかある。

ライフサイクルフック各種

メソッド タイミング
beforeCreate インスタンスが初期化されリアクティブの初期化がされる前
created インスタンスが初期化されリアクティブの初期化がされる後
beforeMount インスタンスがマウントされる前
mounted インスタンスがマウントされる後
beforeUpdate データが更新され、DOMに適用される前
updated データが更新され、DOMに適用される後
beforeDestroy Vueインスタンスが吐きされる前
destroyed Vueインスタンスが吐きされる後
errorCaptured 任意の子孫コンポーネントからエラーが補足されたとき

参考
Vue.jsのライフサイクルメモ

実施されるタイミングのダイアグラムは以下のリンク先を参照すると良いでしょう。
(書籍P48には日本語での同様の図がある)
Vue.jsのライフサイクルダイアグラム図

コラム要約

ちなみに、1行目にある new Vue() を実行するのは基本的に、操作したい全ての部品を包含している要素に対して1つだけ new Vue() を行う。
そこにコンポ―ネントとしてのUI部品を追加してゆくらしい

まとめ

  • Vue.jsではDOM構造の本体はJavaScriptのデータ
  • ディレクティブの値はJavaScriptの式になっている
  • HTMLコーディングの為にコンポーネントを使っても良い
  • 必要なデータやメソッドはオプションに定義してゆく
  • new Vue()は1つ作りコンポーネントでUIを構築する

Laravel本の輪読会を完走した

二か月以上毎週通ったLaravel本の輪読会が先日、最終回を迎えて完走出来ました。

weeyble-php.connpass.com

読んだのは以下の本

PHPフレームワーク Laravel Webアプリケーション開発 バージョン5.5 LTS対応

PHPフレームワーク Laravel Webアプリケーション開発 バージョン5.5 LTS対応

ここでの記事にもしましたが、書籍を毎回1章毎に、参加者のいずれかが担当となって、あらかじめ読み込んで場合によっては資料を書いてそれを元に担当者が解説してゆく、というスタイルです。

PHPフレームワーク Laravel入門

PHPフレームワーク Laravel入門

Laravelの基礎は上の青い本で学び、有志の日本語リファレンスやウェブのノウハウで覚えてきましたが、この本は、さらにその上を行く難しさを感じる様なハードな内容となっていて、おそらく一人で読んで実践していたら心が何度も折れて挫折していたと思います。

これまでプログラム関連のイベントはもくもく会や勉強会等にも通っていましたが、自分が積極的に学んでいるフレームワークの、より高い水準での知識やノウハウを毎回学びつつ、知識を共有できる場に通い、自分よりも多くの知識や技術を持った人に、なんでも質問できたという事は、普段個人でコツコツやっている自分にとって、とても貴重な時間となりました。

最初は担当者の方の話をひたすら聞いてなんとかついてゆくのが精いっぱいでした、実際2章、3章は今でも理解できない事が多く、もう一度読み込もうと思ってますが、4章以降は、実際にアプリを作った自分が見て既存の部分も多くありつつ、新たなノウハウもたくさん学べました。おそらくこの会を一番ありがたがり、最も得たものが多いという自信があります。(なんだそれ)

『9章 テスト』の輪読担当になった事で、マジにやらないとマズイ状況に自らを追い込み、自ら学び、説明できる所までなんとかもって行き、つたないながらも、何とか担当をこなす事が出来ました。
知識の習得は大変でしたが、説明するのは講師の経験が生きたかもしれません。

また、つい先日、最終章の『テスト駆動開発の実践』を事前予習して、いわゆるTDD(テスト駆動開発)を本の内容に基づいて実践してみましたが、これまでプログラミングをして行く上で何度かあった、パッと世界が開ける瞬間を、再び味わう事ができました。

この本は私個人はサンプルとなるソースコードから、暗黙的な筆者の方のメッセージを強く感じました。例えば『3章 アプリケーションアーキテクチャ』『5章 データベース』『9章 テスト』等では、簡単なアプリを実装した上での解説があるのですが、そもそもの本題ではないアプリケーションの書き方に、強いポリシーを感じるのです。

その理論の詳細や意図は実は3章で語られてはいるのですが、私はほとんど理解できてないと思います。ただ、意図の様なものは強く伝わって来る。
そしてこの様なコードの書き方でアプリケーションを作る事の真意が、最終章では体感として理解できるものになっていたのかもしれません。

最後の『テスト駆動開発の実践』ではこれまでこの本で語られたノウハウが全て詰まった状態で簡単なアプリを実装してゆくのですが、まるでゲームの最終面で各面のボスが再度一気に攻めて来るアレの様な感覚ながらも、それを理解しながら、テンポの良い開発をサクサク行い、これまでは理解出来なかった処理の細かな分離などの理由が身をもって体感できました。

それはつまりテスト前提の開発とメンテナンス性ゆえの処理の細分化なのだな、というのが身をもってわかるのです。これはとても快感でした。

しかし、この快感をしってしまうと、自分がこれまで作ったアプリがいかにメンテナンス性の悪い拡張し辛くテストし辛いものであるのか、というのも見えてしまい。自分の作ったものが、エラいヤバいモノに見えてきてしまうのです。
なのでついつい中身を全部作り変えたい衝動に駆られますが、そこはぐっと堪えて、ここで得たノウハウを元に最小のリソースで如何に効果的に安定したものを早く供給できるか、に集中しようと思っています。

しかし、この快感までに辿り付けた輪読会メンバーは残念ながらあまり多くはありませんでしたが、その分、なんとなくゆるい結束力のようなものは出来たかもしれないですね。

次回以降も引き続きVue.jsの輪読会が始まるので、今度はフロント側をリッチにするノウハウを身に付けたいと思います。引き続き新たな知識をどんどん身に付けて、より良いものを作りたい次第。

【感想】知らないと失敗する ソーシャルメディアの黄金法則

こんな本を読んだのでその感想をば。

知らないと失敗する ソーシャルメディアの黄金法則: ?たった一つのメソッドがコミュニティをイキイキさせる? (MyISBN - デザインエッグ社)

知らないと失敗する ソーシャルメディアの黄金法則: ?たった一つのメソッドがコミュニティをイキイキさせる? (MyISBN - デザインエッグ社)

  • 作者: 福岡秀幸,古田英一朗,リンクデザイン株式会社,伊藤みゆき
  • 出版社/メーカー: デザインエッグ社
  • 発売日: 2019/01/01
  • メディア: オンデマンド (ペーパーバック)
  • この商品を含むブログを見る

実は私もソーシャルメディアでコミュニティ的なものを運営した経験があるし、逆に様々なコミュニティに参加してきているが、そこでの共通する法則がうまく言語化されている本です。
概要としては短編小説の体でソーシャルメディアの専門家が対話形式でそのノウハウや法則について詳しく話してくれる構成となってます。
ウェブやリアルに関わらずコミュニティを運営していたり、人が集まる事を価値とする仕事や趣味で携わる人が読むと、とても納得できる様な事が書いてありました。

各章の終わりに本のタイトルにもある法則の要約が書かれているのですが、それをズバリ書いてしまうと、本を読む楽しみが減ってしまうので、個人的な超要約でまとめると以下の3項目に集約されるかもしれません。

  1. 自分が盛り上げようと頑張っても息切れしてしまう
  2. 人を繋げる、紹介する、という事に気を使う
  3. 悪い事が起こらない様、最低限の行動やガイドライン作りのみ行う

私自身がコミュニティを作って維持しようとした際を振り返ってみるとスタートダッシュの際に1,番を極端に頑張って途中で息切れしてしまい、結果として2, をおろそかにして、トラブルが起こった際に3,の方法を取らず、やはり頑張り過ぎて疲れちゃったんだな。というのを、振り返って気付いた次第。

じゃあ、どうすればいいの?という事がこの本には書いてあります。ただ、ページ数も100ページ程で少々物足りなさがあるかもしれませんし、もしかしたらちょっと肩透かしをくらう様な結論かもしれませんが、コミュニティを運営してゆく上での心構えみたいなものが集約されていて、沢山の人の集まりを主催する方や、維持する方にとってはとても良い本ではないかと思います。

実は著者の方は知り合いだったりして、裏話を伺うとこの本は数年以上前に書かれて寝かせていたものだそうで、当時は今より勢いのあったSNSというもののウェブ上のコミュニティ運営のノウハウをご自身の経験から集約したものとなっているそうです。
たしかこの執筆の前後あたりにギークオフィスを立ち上げて、普段はウェブでコミュニティのメンバーがゆるく繋がり、リアルな集まる場所としてのオフィス兼イベントスペースとしての、コミュニティを現在も運営されています。
今流行りのコワーキングスペースの走りみたいなもので、それよりももっと人のつながりを重視するコミュニティ寄りなものを5年以上前からしてるので、かなり時代の先取り感ありますよね。

長い事寝かせておいて、今になって発売に漕ぎつけたのは、実は表紙や中のイラストを描いてくれる方が、ギークオフィスのメンバーなったから、というのも面白いエピソードだと思います。

実はこのブログで紹介した、私が作った滞在者確認アプリはこの方のニーズから生まれたサービスで、今後はこのようなリアルとウェブが融合したコミュニティの価値や存在がもっと大事になって、このような場所から様々なイノベーションが生まれる筈、という見解をもっており、私も完全同意しています。そしてそれは、最近徐々に形になりつつある。

が、もし今またこのような本を書いたら、ギークオフィスをはじめとしたさまざまなコミュニティの新たな見解やノウハウが山の様に溜まっているので、もっと面白い視点で色んな話を読めるかもしれません。
本人をその気にさせる為にも上のリンクからポチっとするのも良いかもしれませんね。

windows vagrant Homestead環境でLaravelアプリを追加する際の覚書

最近windows環境でLaravelを複数追加することがおおくなったので、メモを兼ねて記述しておきます。変な所あったらコメントもらえると助かります。

気を付ける事

まず Homestead.yamlの設定とhostsの設定からおこない、windows側と仮想環境側のフォルダが共有状態になる様に設定が出来るまでがんばる。
これを後回しにして .envの設定やコードとか書いてしまっても、場合によってはフォルダ内のアプリまるごと行方不明になるので、要注意。

Homestead.yamlの設定

# 例えば一つ目のアプリが以下の様にあった場合
folders:
    - map: C:/Vagrant/larabook
      to: /home/vagrant/larabook

sites:
    - map: larabook.test
      to: /home/vagrant/larabook/chapter09/public


Homestead.yamlの設定 二つ目のアプリを追加

---
ip: "192.168.10.10"
# 省略

# こんな風に設定を追加する
folders:
    - map: C:/Vagrant/larabook
      to: /home/vagrant/larabook

# 追加
    # map がwindows側のフォルダ、 larabook_tdd フォルダを作る事
    # to は仮想環境側のディレクトリ やはり larabook_tdd を mkdirする
    - map: C:/Vagrant/add_app_name
      to: /home/vagrant/add_app_name

sites:
    - map: larabook.test
      to: /home/vagrant/larabook/chapter09/public

#追加
    # map はローカル環境で使いたいドメインを指定、.dev .app は設定しない方が良い
    # to は上同様仮想環境側のディレクトリだが、laravelアプリ内のディレクトリ publicまでを指定する
    - map: add_app_name.test
      to: /home/vagrant/add_app_name/public


hostsの設定

windows10の場合以下のファイルを編集する。
最初は読み取り専用だとおもうので、書き込みできるようにwindowsのプロパティ等で設定する。
C:\Windows\System32\drivers\etc\hosts

host ファイル内の最後の行に以下の様に追加
yaml の最初にあるIPとローカル環境で使用したいyamlに設定したドメインを入れる
#でコメント入れられるので、何で追加したかメモとして残しておくと良い

192.168.10.10       larabook.test        # vagrant Laravel study setting
192.168.10.10       add_app_name.test     #Add vagrant Laravel study setting

設定をしたらvagrant 立ち上げてない場合は以下のコマンド
vagrant up

立ち上げてた場合は以下のコマンド(ssh で入っていた場合はいったんexitしてからコマンド)
vagrant provision
変更したyamlの設定ファイルの状態で再度vagrant が動作しますので、windows側、仮想環境側、両方のフォルダを開けて、どちらかにtest様にフォルダなりファイルなりを入れてみてください。
設定が上手くいっていれば、片方に入れたファイルが、もう片方の環境にも反映されるはずです。
上手いかなかった場合は yaml の設定が誤っているか、設定が再度読み込まれていないので、再度確認して、修正してから、 vagrant provisonを行って上手く行くまで試してみてください。
個人的にはこの設定が苦手で何度もやり直すことが多いです。

ファイルが両方の環境で無事共有できるようになったら、laravelをインストールなり、リポジトリクローンなりをして、該当のフォルダ内にLaravelアプリを入れれば設定完了です。

Laravel5.6インストール

以下のコマンドを仮想環境の /home/vagrant で実行する(Laravel5.6を入れる場合)

composer create-project --prefer-dist laravel/laravel add_app_name "5.6.*"

そうすると、一つ下の先ほどmkdirしたフォルダ内 /home/vagrant/add_app_name にアプリがインストールされます。
インストールが終わったら、ブラウザで http://add_app_name.test にアクセスして、すっぴんのLaravelの画面が出れば、設定完了!

しかし、更新しちゃうとマズいファイルはちゃんとエディタで色分けされてない。どうもこのインストール方法だとGitフォルダは作られていないので、add_app_name フォルダ内に移動してからgit init した方が良いですね。.gitignoreファイルは既にあるので、Gitが適用されれば編集しちゃいけないファイルは開発用エディタなら、色が薄く表示されるはずです。
あとはwindows側でエディタを開いて編集してごりごり.envの設定して開発を始める感じです。