Laravel5.4から5.5へ更新する

5.4で作った練習用のサイトを5.5へアップグレードします。

# 親記事
[Laravel 5.5で基本的なCRUDを作る - Qiita](http://qiita.com/sutara79/items/ef30fcdfb7afcb2188ea)


# 更新作業
下記に従って、`composer.json`で指定している依存パッケージのバージョンを変更します。
:link: [アップグレードガイド](https://readouble.com/laravel/5.5/ja/upgrade.html)

なお、アップグレードガイドには記載されていませんが、5.5を新規作成すると[fideloper/proxy](https://github.com/fideloper/TrustedProxy)が依存パッケージに入っていたので、それも追加しました。
Laravel公式は下記のように告知しています。
:link: [Laravel 5.5 Now Includes TrustedProxy - Laravel News](https://laravel-news.com/trusted-proxy)

依存パッケージのバージョン指定が終わったら、`composer update`を実行します。
また、`composer outdated`を実行して、指定されたものの他にも更新がないかを確認します。
その際、[hamcrest/hamcrest-php](https://github.com/hamcrest/hamcrest-php)に更新があることが分かりましたが、`composer.json`には記載されていないパッケージなので放置することにしました。

最終的に下記のようになりました。
基本的にはこれだけでアップグレードは完了です。

```diff:composer.json
     "require": {
         (PHPのバージョンを7以上に)
-        "php": ">=5.6.4",
+        "php": ">=7.0.0",

         "ext-intl": "^1.1",

         (デバッグバー)
-        "barryvdh/laravel-debugbar": "^2.3",
+        "barryvdh/laravel-debugbar": "^3.1",

         (5.5で新規追加)      
+        "fideloper/proxy": "^3.3",

         "fzaninotto/faker": "^1.6",
         
         (ブラウザテストのDusk)
-        "laravel/dusk": "^1.1",
+        "laravel/dusk": "~2.0",

         (Laravel本体)
-        "laravel/framework": "5.4.*",
+        "laravel/framework": "5.5.*",

         "laravel/tinker": "~1.0",
         "predis/predis": "^1.1"
     },
     "require-dev": {
         "heroku/heroku-buildpack-php": "*",
         "mockery/mockery": "0.9.*",

         (ユニットテスト)
-        "phpunit/phpunit": "~5.7"
+        "phpunit/phpunit": "~6.0",

         (5.5で新規追加)
+        "filp/whoops": "~2.0"
     },

(中略)

     "scripts": {
         (5.5で新規追加するスクリプト)
+        "post-autoload-dump": [
+            "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
+            "@php artisan package:discover"
         ]
     },

(中略)

    (上のdiscoverの対象からDuskを外す。理由は後述)
+    "extra": {
+        "laravel": {
+            "dont-discover": [
+                "laravel/dusk"
+            ]
+        }
+    },
```

# 個別の対応
## SQLiteではDuskのテストで接続に失敗する
Laravel5.4では、データベースとしてSQLiteを使っていました。
5.5に上げた後でDuskのテストを実行すると下記のようなエラーが。
SQLiteファイルが見つからないようです。

```text:PowerShell
> php artisan dusk

(中略)

ErrorException: unlink(C:\(中略)\database\dusk_local.sqlite): Resource temporarily unavailable
```

### 解決策: SQLiteではなくMySQLを使う
原因は分かりません。
ただ、5.4の時から、SQLiteファイルの名前をデフォルトの`database.sqlite`以外にすると接続できない場合があって、原因も分からないのでずっと不安でした。
これを機に、ローカルではMySQLを使うことにします。
なお、本番やTravisCIではPostgresを使っています。

## TravisCIでDusk関連のエラーが発生
Travis CIで下記のような例外が発生します。

```
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover
                                           
  [Exception]                              
  It is unsafe to run Dusk in production.  
                                           
Script @php artisan package:discover handling the post-autoload-dump event returned with error code 1
The command "composer install --no-interaction" failed. Retrying, 2 of 3.
```

### 解決策: discoverの対象からDuskを外す
`It is unsafe to run Dusk in production.`というメッセージを元に検索し、下記のページで解決策を得られました。

:link: [&quot;It is unsafe to run Dusk in production.&quot; error when trying to deploy](https://laracasts.com/discuss/channels/forge/it-is-unsafe-to-run-dusk-in-production-error-when-trying-to-deploy)

つまり、`composer.json`に下記を追加するだけです。
これでTravisCIでのテストが通りました。

```text:composer.json
    "extra": {
        "laravel": {
            "dont-discover": [
                "laravel/dusk"
            ]
        }
    },
```

他にも"laravel/dusk"を"require"ではなく"require-dev"に移すという方法もあるようですが、上の方法はLaravel作者のTaylor Otwellさんも勧めている方法ですし、主流に合わせようと思いました。

## Debugbarの設定ファイルを生成しなおす
[Laravel Debugbar](https://github.com/barryvdh/laravel-debugbar)の2.x系から3.x系への移行に伴い、設定ファイルが少し変更されています。
設定できる項目が少し増えているほか、Debugbarの表示・非表示の設定を環境設定ファイル`.env`でできるようになっています。

```bash:.env
# 初期値
DEBUGBAR_ENABLED=null

# 必ず表示
DEBUGBAR_ENABLED=true

# 必ず非表示
DEBUGBAR_ENABLED=false
```

よって、既存の`config/debugbar.php`を避難した上で下記のコマンドで設定ファイルを生成しなおすことをお勧めします。

```text:PowerShell
> php artisan vendor:publish --provider="Barryvdh\Debugbar\ServiceProvider"
```

:link: 関連記事: [Laravel Debugbarを使う](https://qiita.com/drafts/9fd442a81001842aeba1/edit)

## クエリビルダの最後にはgetなどが必要
たとえばPostコントローラで記事一覧を新しい順に取得する場合。
Laravel5.4では下記のコードでOKでした。

```php:app/Http/Controllers/PostController.php
    public function index()
    {
        $posts = Post::latest();
        return view('posts.index', ['posts' => $posts]);
    }
```

しかし5.5では、最後に`get()`を実行しなければビューで表示できる形式になりません。

```php:app/Http/Controllers/PostController.php
    public function index()
    {
        $posts = Post::latest()->get(); // 最後に get() が必要。
        return view('posts.index', ['posts' => $posts]);
    }
```

公式ドキュメントを確認すると、前々から`get()`をつけるのが正式だったようです。
`latest()`, `orderBy()`などは並べ替えるだけなので、ビューで表示できる形にするには`get()`, `first()`, `paginate()`などの目的の表示形式に応じたをメソッド通す必要があるようです。

# Duskはヘッドレスがデフォルトとなった
Laravel5.4ではブラウザテストのDuskを実行するとブラウザが起動して、ボタンをクリックしたりフォームに文字を入力するなどのテストに記述した動作が自動で実行される様子を眺めることができました。
Laravel5.5ではヘッドレスでの実行がデフォルトとなり、テストのたびにブラウザが起動することはなくなり、その分テスト時間が短くなりました。
5.5と同じ設定にするには、`DuskTestCase.php`を下記のように修正します。

```diff:tests/DuskTestCase.php
+use Facebook\WebDriver\Chrome\ChromeOptions;
 
 abstract class DuskTestCase extends BaseTestCase
 {
     protected function driver()
     {
+        $options = (new ChromeOptions)->addArguments([
+            '--disable-gpu',
+            '--headless'
+        ]);
+
         return RemoteWebDriver::create(
-            'http://localhost:9515', DesiredCapabilities::chrome()
+            'http://localhost:9515', DesiredCapabilities::chrome()->setCapability(
+                ChromeOptions::CAPABILITY, $options
+            )
         );
     }
```

ただ、動作を目で確認したい場合もあると思います。
そんな時は`--headless`をコメントアウトしてください。5.4と同じようになります。
:warning: ただし、コメントアウトは一時的なものとして必ず元に戻してください。
TravisCIでテストする場合、ヘッドレスを指定しなければエラーになってしまいます。

```php
        $options = (new ChromeOptions)->addArguments([
            '--disable-gpu',
            // '--headless' ! 後で必ず元に戻すこと
        ]);
```