Laravelの開発環境を仮想マシン上に構築してVueのサンプルを動かしてみる

### Laravelの開発環境を構築したときの手順 2018/03/05

仮想マシンを使ったLaravelのプロジェクトを動かす手順のメモです。

## 仮想マシン環境を準備します
vagrant と　virtualboxをインストールします

```
$ sudo apt-get install virtualbox
$ sudo apt-get install vagrant

$ vagrant --version
Vagrant 1.9.1
```
実機と仮想マシン間の通信にsshキーが必要になるので
あらかじめ登録しておいてください（省略）

--------------------------------------------------------------------------------
## 作業用フォルダーを作りvagrantを設定します。

仮想マシンの構成ファイルを配置するフォルダを作ります。（そこに移動します。）

```
$ mkdir ~/ProjectX
$ cd ~/ProjectX
```

仮想マシンの構成ファイル（Homestead）をクローンします
laravelのプロジェクトに必要となるものがあらかじめ組み込まれています。
（構成を調整＆準備する手間を省くことができます。）

```
$ git clone https://github.com/laravel/homestead.git Homestead
$ cd ./Homestead/
$ ll
[ken:Homestead (master)]$ ll
合計 144
drwxr-xr-x 9 ken ken  4096  3月  5 12:51 ./
drwxr-xr-x 3 ken ken  4096  3月  5 12:51 ../
drwxr-xr-x 8 ken ken  4096  3月  5 12:51 .git/
-rw-r--r-- 1 ken ken    14  3月  5 12:51 .gitattributes
drwxr-xr-x 2 ken ken  4096  3月  5 12:51 .github/
-rw-r--r-- 1 ken ken    81  3月  5 12:51 .gitignore
-rw-r--r-- 1 ken ken   261  3月  5 12:51 .travis.yml
-rw-r--r-- 1 ken ken   187  3月  5 12:51 CHANGELOG.md
-rw-r--r-- 1 ken ken  1077  3月  5 12:51 LICENSE.txt
-rw-r--r-- 1 ken ken  1655  3月  5 12:51 Vagrantfile
drwxr-xr-x 2 ken ken  4096  3月  5 12:51 bin/
-rw-r--r-- 1 ken ken   809  3月  5 12:51 composer.json
-rw-r--r-- 1 ken ken 63327  3月  5 12:51 composer.lock
-rw-r--r-- 1 ken ken   265  3月  5 12:51 init.bat
-rw-r--r-- 1 ken ken   250  3月  5 12:51 init.sh
-rw-r--r-- 1 ken ken   383  3月  5 12:51 phpunit.xml.dist
-rw-r--r-- 1 ken ken  1404  3月  5 12:51 readme.md
drwxr-xr-x 3 ken ken  4096  3月  5 12:51 resources/
drwxr-xr-x 2 ken ken  4096  3月  5 12:51 scripts/
drwxr-xr-x 4 ken ken  4096  3月  5 12:51 src/
drwxr-xr-x 4 ken ken  4096  3月  5 12:51 tests/

```

## 初期化
初期化（init.sh）すると Homestead.yaml ,after.sh などが生成されます。
（composer.jsonの内容も書き換わります）

```
$ bash init.sh 
Homestead initialized!
```
##仮想マシン上のフォルダと実機のフォルダの共有設定をする

以下のデフォルトの設定で、
仮想マシン上の/home/vagrant/codeと
実機上の ~/code の同期が取られます。
(後ほど編集しますが・・・とりあえずこのままでOK!)　

```Homestead.yaml
---
ip: "192.168.10.10"
memory: 2048
cpus: 1
provider: virtualbox

authorize: ~/.ssh/id_rsa.pub

keys:
    - ~/.ssh/id_rsa

folders:
    - map: ~/code             こちらが実機上のパス
    to: /home/vagrant/code    こっちがVagrant上のパス

sites:
    - map: homestead.test
      to: /home/vagrant/code/public

databases:
    - homestead
```

以下のコマンドで仮想サーバーを起動します（初期化処理を行ったフォルダ上）
雛形イメージ（hostead）をベースに仮想マシンを構成＆起動してくれます
```
$ vagrant up
```

起動していることを確認します

```
$ vagrant status
Current machine states:

homestead-7               running (virtualbox)
```

--------------------------------------------------------------------------------
##sshで仮想マシンに入る
ローカルマシンから仮想サーバにログインします（仮想マシン上のシエルに移動します）

```
vagrant ssh
```
仮想マシン上のプロジェクトを作成するフォルダへ移動する

```
cd ~/code
```

ここにLaravelプロジェクトの雛形を生成する（バージョンを5.5としました）
プロジェクトフォルダ名は、Laravel55としました。
カレントデイレクトリ上に指定したバージョンの雛形がダウンロードされます。

```
composer create-project --prefer-dist laravel/laravel=5.5.* Laravel55
```

ローカル側の~/Code以下にもLaravelプロジェクトが同期生成されています
これを確認。(わりと時間がかかります)

```
cd ~/code/Laravel55
```
# 動作確認？！
実機のブラウザから
192.168.10.10
にアクセスすればLaravelのトップ画面が表示されるはずだが・・・

No input file specified.

となるので・・・仮想マシンにsshで入りnginxのログを確認する

```
sudo tail -f /var/log/nginx/homestead.test-error.log

2018/02/20 06:13:26 [error] 1501#1501: *1 FastCGI sent in stderr:
"Unable to open primary script: /home/vagrant/code/public/index.php (No such file or directory)" while reading response header from upstream, client: 192.168.10.1, server: homestead.test, request: "GET /Laravel HTTP/1.1", upstream: "fastcgi://unix:/var/run/php/php7.2-fpm.sock:", host: "192.168.10.10"
```

つまりフォルダのマッピングがあっていない様子　
sshを抜け、一旦仮想マシンを終了させます。

```
exit
vagrant halt
```

Homestead.yamlを修正する（sites:以下の部分を書き換える）

```Homestead.yamlの確認

folders:
    - map: ~/code/Laravel55
      to: /home/vagrant/code/Laravel55

sites:
    - map: homestead.test
      to: /home/vagrant/code/Laravel55/public
```

# 書き換えたHomestead.yamlを読みなおして、仮想マシンを再起動させる

```
vagrant reload --provision
```

実機のブラウザから
192.168.10.10
にアクセスするとLaravelのトップ画面が表示されました。

# macでは、・・・以下のメッセージが出たので・・・

The specified host network collides with a non-hostonly network!
This will cause your specified IP to be inaccessible. Please change
the IP or name of your host only network so that it no longer matches that of
a bridged or non-hostonly network.）

Homestead.yaml を　ip: "192.168.56.1" として動かしました
なお８０００ポートにポートフォワードされていましたので以下のようにアクセスしました
http://192.168.56.1:8000/


---
# Vueのサンプルを動かす

はじめに、nodeをインストールしておく。（省略）

プロジェクトのデイレクトリでnodeのモジュールをインストールする
（package.json 上に設定されているモジュールが取り込まれます。
今回は何も追加していないのでやらなくてもOKかも）

```
npm install
```


```package.json 
{
    "private": true,
    "scripts": {
        "dev": "npm run development",
        "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
        "watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
        "watch-poll": "npm run watch -- --watch-poll",
        "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
        "prod": "npm run production",
        "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
    },
    "devDependencies": {
        "axios": "^0.17",
        "bootstrap-sass": "^3.3.7",
        "cross-env": "^5.1",
        "jquery": "^3.2",
        "laravel-mix": "^1.0",
        "lodash": "^4.17.4",
        "vue": "^2.5.7"
    }
}
```


Laravelのプロジェクト内にVueのサンプルコンポーネントが入っています。
（以下の２つの部品がそれ・・・）
これを動かしてみます。

##部品１：コンポーネントのサンプル
```~/code/Laravel55/resources/assets/js/components/ExampleComponent.vue
<template>
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <div class="panel panel-default">
                    <div class="panel-heading">Example Component</div>

                    <div class="panel-body">
                        I'm an example component!
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        mounted() {
            console.log('Component mounted.')
        }
    }
</script>

```

##部品２：サンプルコンポーネントを割り当てる

```~/code/Laravel55/resources/assets/js/app.js

/**
 * First we will load all of this project's JavaScript dependencies which
 * includes Vue and other libraries. It is a great starting point when
 * building robust, powerful web applications using Vue and Laravel.
 */

require('./bootstrap');

window.Vue = require('vue');

/**
 * Next, we will create a fresh Vue application instance and attach it to
 * the page. Then, you may begin adding components to this application
 * or customize the JavaScript scaffolding to fit your unique needs.
 */

Vue.component('example-component', require('./components/ExampleComponent.vue'));

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


```

### Vueを載せるBlade（testVue.blade.php）を用意する


```~/code/Laravel55/resources/views/testVue.blade.php
<!DOCTYPE html>
<html lang="{{ config('app.locale') }}">
    <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>Vue test</title>
        <link rel="stylesheet" href="css/app.css">
        <script>
            window.Laravel = {};
            window.Laravel.csrfToken = "{{ csrf_token() }}";
        </script>
    </head>
    <body>
        <div id="app">
          <example-component></example-component>
        </div>
    </body>
    <script src="js/app.js"></script>
</html>
```

コンポーネントを差し込む部分およびｊｓを読み込む部分
app.jsに書いた　el: '#app' で、div id="app"と対応させ、
Vue.component('example-component', require('./components/ExampleComponent.vue'));
の部分でVueのコンポーネントとexample-componentタグの対応づけている。

``` 
    <body>
        <div id="app">
          <example-component></example-component>
        </div>
    </body>
    <script src="js/app.js"></script>
```

## ルーテイングを追加
testVue　というパスでアクセスしたら　
testVue　というView(ブレードファイル)を呼び出すこということ。

```~/code/Laravel55/app/Http/routes.php
Route::get('/testVue', function () {
    return view('testVue');
});

```

http://192.168.10.10/testVue　
にアクセスしてみて動作確認する（以下のように表示されていればオッケー）

![testvue.png](https://qiita-image-store.s3.amazonaws.com/0/230615/1a91d14e-aeb6-fb17-86ef-5540e89210c3.png)









実験
ExampleComponentをコピーしてExampleComponent2.vueを作り中身を以下のように書き換えます。



``` ~/code/Laravel55/resources/assets/js/components/ExampleComponent.vue
<template>
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <div class="panel panel-default">
                    <div class="panel-heading">コンポーネント #2</div>
                    <div class="panel-body">
                        例 #2
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        mounted() {
            console.log('Component mounted #2.')
        }
    }
</script>
``` 

app.jsを以下のように書き換えます

``` ~/code/Laravel55/resources/assets/js/app.js

require('./bootstrap');

window.Vue = require('vue');

/**
 * Next, we will create a fresh Vue application instance and attach it to
 * the page. Then, you may begin adding components to this application
 * or customize the JavaScript scaffolding to fit your unique needs.
 */

Vue.component('example-component', require('./components/ExampleComponent.vue'));
Vue.component('example-component2', require('./components/ExampleComponent2.vue'));

// const app = new Vue({
//     el: '#app'
// });


const app = new Vue({});

// import router from './router'
// import VueRouter from 'vue-router'
// Vue.use(VueRouter)
// const app = new Vue({
//     router,
// });
app.$mount('#app');
``` 

インスタンス？の生成とタグappへのアサインを別々に書くこともできます。
const app = new Vue({});

コピーしたコンポーネントも定義しています。
Vue.component('example-component2', require('./components/ExampleComponent2.vue'));

bladeを以下のように編集します

```
<!DOCTYPE html>
<html lang="{{ config('app.locale') }}">
    <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>Vue test</title>
        <link rel="stylesheet" href="css/app.css">
        <script>
            window.Laravel = {};
            window.Laravel.csrfToken = "{{ csrf_token() }}";
        </script>
    </head>
    <body>
        <h1>testVue page</h1>
        <div id="app">
        <example-component1></example-component1>
        <example-component2></example-component2>
        </div>
    </body>
    <script src="js/app.js"></script>
</html>
```
ブラウザから確認します。追加したコンポーネントも見ることができたとおもいます。











### vue-routerを使う
package.json を編集します。(以下の記述を追加する)


```
    "dependencies": {
        "vue-router": "^3.0.1"
    }
```


```package.json
{
    "private": true,
    "scripts": {
        "dev": "npm run development",
        "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
        "watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
        "watch-poll": "npm run watch -- --watch-poll",
        "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
        "prod": "npm run production",
        "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
    },
    "devDependencies": {
        "axios": "^0.17",
        "bootstrap-sass": "^3.3.7",
        "cross-env": "^5.1",
        "jquery": "^3.2",
        "laravel-mix": "^1.0",
        "lodash": "^4.17.4",
        "vue": "^2.5.7"
    },
    "dependencies": {
        "vue-router": "^3.0.1"
    }
}
```
vue-routerの部品（モジュール）をインストールする
(./node_modules/以下にモジュールが落ちてきます)

```
npm install
```

パッケージマネージャでdevというスクリプトを実行すると
/js/app.js が生成されます。

```
npm run dev
```
ちなみに開発中は以下のコマンドを実行しておくと、変更を感知して自動でビルドしてくれます

```
npm run watch

もしくは

npm run polling
```

## ルーテイングを追加
SPA用のルーテイングを追加します。

```~/code/Laravel55/app/Http/routes.php
Route::get('/{any}', function () {
    return view('app');
})->where('any', '.*');
```

ブレードをコピーして以下のように編集しますテンプレートを用意します・・・作業中・・・
~/code/Laravel55/resources/views/testVue2.blade.php

<!DOCTYPE html>
<html lang="{{ config('app.locale') }}">
<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>Vue test</title>
        <link rel="stylesheet" href="css/app.css">
        <script>
            window.Laravel = {};
            window.Laravel.csrfToken = "{{ csrf_token() }}";
        </script>
    </head>
    <body>
        <h1>testVue2</h1>

        <div id="app">
            <!-- <router-link to="/about">about</router-link>
            <router-link to="/menu">menu</router-link>
            -->
            <example-component2></example-component2>

            <!-- <router-view></router-view> -->
        </div>
    </body>
    <script src="js/app.js"></script>
</html>





```~/code/Laravel/resources/assets/js/router.js
import Vue from 'vue'
import VueRouter from 'vue-router'


const router = new VueRouter({
    mode: 'history',
    routes: [
    { path: '/menu', component: require('./components/Menu.vue')
    },
    { path: '/v005', component: require('./components/Enumerate.vue')
    },
    { path: '/ApplicationSheet', component: require('./components/ApplicationSheet.vue')
    },
{ path: '*',redirect: '/'}
]
});

export default router
```