メモ書き : Laravel8 Release & Upgrade

2020/09/08 リリース。バグフィックス期間は 2021/03/08 セキュリティフィックスは2021/09/08 までという予定。

そして、新機能が多いため Upgrade の量は少ないですが、factory をゴリゴリ使っているとちょっと注意です。（ migration の `schema:dump` やった後の `migrate` したときの挙動が怖そうなので、そこらへんは自己責任でしてください）

- see : https://laravel.com/docs/8.x/releases
- see : https://laravel.com/docs/8.x/upgrade

アップグレードに対する更新をソースコード単位で見たい場合は [Github comparision tool](https://github.com/laravel/laravel/compare/7.x...master) を見ると良いですよ。

個人的なメモ: upgrade の時は phpstan で静的解析を通すのが良いですよーよー。

# [新機能] Laravel Jetstream

see : https://github.com/laravel/jetstream

新しいパッケージだそうです。

Scaffolding の [livewire](https://laravel-livewire.com/) か [Inertia](https://inertiajs.com/)を使って、ええ感じに Vue や [Tailwind CSS](https://tailwindcss.com/) っぽく使って…？

なんやこれ全くわからん。bladeを抜かした管理画面を自動で作るよってことかしら。

# [新機能] Model Directory

Eloquent Model の初期位置が `app/Models` の中になりました。

# [新機能] Model Factory Classes

factory がクラスになりました。例えば User factory が旧だとベタなPHPスクリプトだったのが、クラスで指定するようになります。

旧 Factory を使う場合は [laravel/legacy-factories](https://github.com/laravel/legacy-factories) を使うことになります。極力書き換えるのをおすすめします。

```
<?php
/** @var \Illuminate\Database\Eloquent\Factory $factory */

use Faker\Generator as Faker;

$factory->define( \App\Eloquent\User::class, function (Faker $faker){
    return [
            'name' => $this->faker->name,
            'email' => $this->faker->unique()->safeEmail,
            'email_verified_at' => now(),
            'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
            'remember_token' => Str::random(10),
    ];
} );
```

新::

```
<?php

namespace Database\Factories;

use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;

class UserFactory extends Factory
{
    /**
     * The name of the factory's corresponding model.
     *
     * @var string
     */
    protected $model = User::class;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            'name' => $this->faker->name,
            'email' => $this->faker->unique()->safeEmail,
            'email_verified_at' => now(),
            'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
            'remember_token' => Str::random(10),
        ];
    }
}
```


これに伴い、Eloquent 側からfactory を作ることになるそうです。

```
<?php

use App\Model\User;

User::factory()->count(50)->create();
```


# [新機能] Migration Squash

SQL で書かれたスキーマの出力ができるようになります。出力されたスキーマは `database/schema` に保存されます。

migration にも関わってくる。(後で）

```
php artisan schema:dump
```

# [新機能] Job Batching

`Bus` でバッチ処理が追加されて、axios みたいな書き方で使えるっぽいです。

```
<?php
use App\Jobs\ProcessPodcast;
use App\Podcast;
use Illuminate\Bus\Batch;
use Illuminate\Support\Facades\Batch;
use Throwable;

$batch = Bus::batch([
    new ProcessPodcast(Podcast::find(1)),
    new ProcessPodcast(Podcast::find(2)),
    new ProcessPodcast(Podcast::find(3)),
    new ProcessPodcast(Podcast::find(4)),
    new ProcessPodcast(Podcast::find(5)),
])->then(function (Batch $batch) {
    // All jobs completed successfully...
})->catch(function (Batch $batch, Throwable $e) {
    // First batch job failure detected...
})->finally(function (Batch $batch) {
    // The batch has finished executing...
})->dispatch();

return $batch->id;
```


# [新機能] Improved Rate Limit

Requtest Rate Limit を `throttle` ミドルウェアで制御してるが、もうちょっとフレキシブルにレートリミットを変えられるようになるっぽいです。

例えば、会員ユーザのレートリミットは無し、それ以外はレートリミットは100回/分にする、とする場合は下記のように変更できるみたいです。

```
<?php
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Support\Facades\RateLimiter;


// おそらく AppServiceProvider の中で設定
RateLimiter::for('uploads', function (Request $request) {
    return $request->user()->vipCustomer()
                ? Limit::none()
                : Limit::perMinute(100);
});
```

ミドルウェアの `throttole` で指定することで使える様になるみたいです。

```
Route::middleware(['throttle:uploads'])->group(function(){
  Route::post('/audio', function(){ });
  
  Route::post('/video', function(){ });
});
```



# [新機能] Improved Maintenance Mode

`php artisan down` でメンテナンスモードにした時の挙動を云々。

1. --secret='1630542a-246b-4b66-afa1-dd72a4c43515'

  このオプションを使うことで `/` に来たユーザは `/1630542a-246b-4b66-afa1-dd72a4c43515` にリダイレクトされます。

2. --render='errors::503'

  このオプションを使うことで、表示するテンプレを指定することができる。
  
# [新機能] Closure Dispatch/Chain

dispatch helper に `->catch(function(){})` ができるようになりました。おそらく、上記の `Bus` と同じ理屈。

```
<?php

use Throwable;

dispatch(function () use ($podcast) {
    $podcast->publish();
})->catch(function (Throwable $e) {
    // This job has failed...
});
```

# [新機能] Dynamic Blade Components

`Blade::component('package-alert', AlertComponent::class);` で登録したコンポーネントを `<x-package-alert/>` とテンプレート側に書くことで使えるようになります。

クラス名は `camelCase` で書き、コンポーネント名は `kebab-case` で書くみたい。

## Component Methods

コンポーネントテンプレート内でメソッドを動かすことができる。

```
/**
 * Determine if the given option is the current selected option.
 *
 * @param  string  $option
 * @return bool
 */
public function isSelected($option)
{
    return $option === $this->selected;
}
```

```
<option {{ $isSelected($value) ? 'selected="selected"' : '' }} value="{{ $value }}">
    {{ $label }}
</option
```

(何か vue みたいだなとぼんやり)

# [新機能] Event Listener Improvements

Facade で `\Event::listen` をする時に、Queueを使うようにデコレートする事ができます。

```
use App\Events\PodcastProcessed;
use function Illuminate\Events\queueable;
use Illuminate\Support\Facades\Event;

Event::listen(queueable(function (PodcastProcessed $event) {
    //
}));
```

そして `queue job` のように細かくしてする事ができて `->catch` チェインができます。

```

Event::listen(queueable(function (PodcastProcessed $event) {
    //
})->catch(function (PodcastProcessed $event, Throwable $e) {
    // The queued listener failed...
})->onConnection('redis')
  ->onQueue('podcasts')
  ->delay(now()->addSeconds(10))
);
```


# [新機能] Time Testing Helpers

`Carbon::now()` で返す時間を指定することができます。


# [新機能] Artisan serve Improvements

`.env` ファイルを更新したばあいに、`artisan serve` は自動に設定を読み直します。

# [新機能] Tailwind Pagination Views

Pagination のテンプレートに今までの Bootstrap3, Bootstrap4 の他に [Tailwind](https://tailwindcss.com/) が使えます。



# [Upgrade] パッケージ依存

- `"laravel/framework": "^8.0"`
- `"nunomaduro/collision": "^5.0"`
- `"guzzlehttp/guzzle": "^7.0.1"`
- `"facade/ignition": "^2.3.6"`

他のパッケージを使っているばあいは、それらもアップデートしてください

- [https://github.com/laravel/horizon/blob/master/UPGRADE.md](Horizon v5.0)
- [https://github.com/laravel/passport/blob/master/UPGRADE.md](Passport v10.0)
- [Socialite v5.0](https://github.com/laravel/socialite/blob/master/UPGRADE.md)
- [Telescope v4.0](https://github.com/laravel/telescope/releases)

# [Upgrade][Medium] Use PHP >=7.3.0

事情により PHP は 7.3.0 以上を指定してください。

# [Upgrade][Low] `isset` method

`Illuminate\Support\Collection` の `offsetExists` の挙動がかわりました。ので `isset` で確認した時の挙動が変わります。

```
<?php

$collection = collect([null]);

// Laravel 7.x - true
isset($collection[0]);

// Laravel 8.x - false
isset($collection[0]);
```

# [Upgrade][High] Model Factories

model factories がクラス化されました。7.x までの [factory を書き換え](#https://laravel.com/docs/8.x/database-testing#creating-factories)をせずに使い続ける場合は `laravel/legacy-factory` を使う必要があります。

# [Upgrade][Low] The Castable Interface

`Castable` の `castUsing` の引数 `$arguments` に、`array`のタイプ指定が加わりましたので、追加をしてください。

# [Upgrade][Low] Increment / Decrement Events

model の `update` および `save` が動いた時に `increment`,`decrement` インスタンスメソッドが動きます。

# [Upgrade][Low] The Dispatcher Contract

`Illuminate\Contracts\Events\Dispatcher` の `listen` メソッドの第二引数 `$listener` の標準値に `null` を付けられました。

```
public function listen($events, $listener = null);
```

# [Upgrade][Optional] Mentenance Mode Updates

新しく入った機能 `--render` 等を使う場合は `public/index.php` を更新してください。この条件分岐の行は `LARAVEL_START` の直下に書く必要があります。

```
<?php
define('LARAVEL_START', microtime(true));

if (file_exists(__DIR__.'/../storage/framework/maintenance.php')) {
    require __DIR__.'/../storage/framework/maintenance.php';
}
```

# [Upgrade][Low] Manager $app Property

`Illuminate\Support\Manager` クラスの `$app` プロパティが消えました。もしそのプロパティを使用している場合は `$container` プロパティを使用してください。

# [Upgrade][Low] The elixir Helper

`elixir` ヘルパーは削除されました。[Laravel Mix](https://github.com/JeffreyWay/laravel-mix) に移行してください。

# [Upgrade][Low] Mail::sendNow Method

`Mail` facade にあった `sendNow` メソッドは削除されました。 `send` メソッドを使ってください。

# [Upgrade][High] Pagination Defaults

Paginate の標準テンプレートが [Tailwind CSS](https://tailwindcss.com/) になりました。いままでの BootStrap を使い続ける場合は `AppServiceProvider` の `boot` メソッドに `\Illuminate\Pagination\Paginator::useBootstrap();` を記入してください。


# [Upgrade][High] Queue::retryAfter method / property

QueuedJob, Mailer, Notification, Listener にある `retryAfter` メソッドと `retryAfter` プロパティの名前が `backoff` に変更されました。

# [Upgrade][High] Queue::timeoutAt property

QueueJob、Notification, Listener の `timeoutAt` プロパティが `retryUntil` になりました。

# [Upgrade][Optional] Failed Jobs Table Batch Support

queue_driver が`database` で `failed_jobs` を使用している時に、`uuid` フィールドが必要になります。

```
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

Schema::table('failed_jobs', function (Blueprint $table) {
    $table->string('uuid')->after('id')->unique();
});
```

次に `queue.php` の `failed.driver` に `database-uuids` を設置します。

# [Upgrade][Low] The cron-expression Library

Cron 書式の解析に使用している `dragonmantank/cron-expression` のバージョンが `3.x` に更新されました。
下手に込み入った書き方をしている場合だと意図しない時間に動きますので、[変更履歴](https://github.com/dragonmantank/cron-expression/blob/master/CHANGELOG.md)を見て確認をする必要があります。

# [Upgrade][Low] The Session Contract

`\Session::pull()` メソッドが追加されました。

```
/**
  * Get the value of a given key and then forget it.
  *
  * @param  string  $key
  * @param  mixed  $default
  * @return mixed
  */
 public function pull($key, $default = null);
```

# [Upgrade][Medium] Testing, The assertExactJson Method

`assertExactJson` メソッドは数値キーの順番が同じである事をチェックするようになりました。順番が違っても良い場合は `assertSimilarJson` を使うようにしてください。

ぼんやり:: こういう事？

```
$asset = [ 0 =>1,  1 =>1,  2 =>1];
$data  = ['1'=>1, '0'=>1, '2'=>1];
$this->assertExactJson(json_encode($asset), json_encode($data)) // => false
$this->assertSimilarJson(json_encode($asset), json_encode($data)) // => true
```

# [Upgrade][Low] Database Rule Connections

`unique`,`exists` ルールに `getConnectionName` メソッドが追加されました。