下書き:Lravel新機能
==========
# 以下に清書!!
## https://hackmd.io/mTyILcVNTFq_kiN_2ybSvg
------------------------------------------------------------
------------------------------------------------------------
------------------------------------------------------------
------------------------------------------------------------
------------------------------------------------------------
https://laravel.com/docs/master/releases
https://laravel-news.com/laravel-10
## のこり調べること
## [Laravel Pennant](https://laravel.com/docs/10.x/pennant)
機能フラグを追加するためのファーストパーティパッケージ。(Compoer 経由でインストールする)
### インストール手順
``` bash
composer require laravel/pennant
php artisan vendor:publish --provider="Laravel\Pennant\PennantServiceProvider"
php artisan migrate
```
### サービスプロバイダに機能フラグを追加するパターン
```php=
<?php
namespace App\Providers;
use App\Models\User;
use Illuminate\Support\Lottery;
use Illuminate\Support\ServiceProvider;
use Laravel\Pennant\Feature;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Feature::define('new-api', fn (User $user) => match (true) {
$user->isInternalTeamMember() => true,
$user->isHighTrafficCustomer() => false,
default => Lottery::odds(1 / 100),
});
}
}
```
上記により実現できる機能フラグの管理。
* 内部メンバーは 新しいAPI が利用可能
* トラフィックの多い顧客は、新しい API が利用不可
* それ以外の場合、100 分の 1 の確率で利用可能
### クラスベースの機能
サービスプロバイダに定義するのではなく、機能フラグをクラスで管理することも可能。
```bash=
php artisan pennant:feature NewApi
```
```php=
<?php
namespace App\Features;
use Illuminate\Support\Lottery;
class NewApi
{
/**
* Resolve the feature's initial value.
*/
public function resolve(User $user): mixed
{
return match (true) {
$user->isInternalTeamMember() => true,
$user->isHighTrafficCustomer() => false,
default => Lottery::odds(1 / 100),
};
}
}
```
### 機能フラグの利用
`Feature::active('KEY名')` で取得することができる
```php=
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Laravel\Pennant\Feature;
class PodcastController
{
/**
* Display a listing of the resource.
*/
public function index(Request $request): Response
{
return Feature::active('new-api')
? $this->resolveNewApiResponse($request)
: $this->resolveLegacyApiResponse($request);
}
// ...
}
```
#### クラスベースの機能フラグを利用している場合
機能フラグを管理しているクラス名を指定する必要がある。
```php=
<?php
namespace App\Http\Controllers;
use App\Features\NewApi;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Laravel\Pennant\Feature;
class PodcastController
{
/**
* Display a listing of the resource.
*/
public function index(Request $request): Response
{
return Feature::active(NewApi::class)
? $this->resolveNewApiResponse($request)
: $this->resolveLegacyApiResponse($request);
}
// ...
}
```
### Blade内での利用方法
```htmlembedded=
@feature('new-api')
<!-- 'site-redesign' is active -->
@else
<!-- 'site-redesign' is inactive -->
@endfeature
```
## [Processes](https://laravel.com/docs/10.x/processes)
プロセス呼び出しがファサード経由で実行できる。
```php=
use Illuminate\Support\Facades\Process;
$result = Process::run('ls -la');
return $result->output();
```
### 便利なメソッド群
```php=
$result = Process::run('ls -la');
$result->successful();
$result->failed();
$result->exitCode();
$result->output();
$result->errorOutput();
```
### 例外
```php=
$result = Process::run('ls -la')->throw();
$result = Process::run('ls -la')->throwIf($condition);
```
## [テストのプロファイル オプション](https://laravel.com/docs/10.x/releases#test-profiling)
最も遅いテストを一覧表示できる。(最大10個)
## [Pest Scaffolding](https://laravel.com/docs/10.x/releases#pest-scaffolding)
## [特定の長さの安全でランダムなパスワード生成ヘルパー Str::password()](https://laravel.com/docs/10.x/helpers#method-str-password)
このStr::password方法を使用して、特定の長さの安全でランダムなパスワードを生成できます。パスワードは、文字、数字、記号、およびスペースの組み合わせで構成されます。デフォルトでは、パスワードの長さは 32 文字です。
## [Customize the path of config files](https://benjamincrozat.com/laravel-10#customize-the-path-of-config-files)
## [doctrine/dbal is not needed anymore to modify columns in migrations](doctrinedbal-is-not-needed-anymore-to-modify-columns-in-migrations)
## [Laravel 10 requires at least Composer 2.2](https://benjamincrozat.com/laravel-10#laravel-10-requires-at-least-composer-22)
## [Dropped support for PHP 8.0](https://benjamincrozat.com/laravel-10#dropped-support-for-php-80)
## [Dropped support for Predis v1](https://benjamincrozat.com/laravel-10#dropped-support-for-predis-v1)
Laravel10 を目の前でインストールして使ってみる
## やること
* 過去のLaravel回のまとめ(久山)
* [PHPerによるPHPerのための「Laravel8を中心に語り合う」TechCafe](https://hackmd.io/@S051_ovFTzmLW3plu6ehiw/BkiwDx9IP)
* [PHPerのための「Laravel/PHP8/Dockerで開発環境作りを語り合う」TechCafe](https://hackmd.io/@hrxVDayfRGeTR-1JBV3QLA/H1NeB2asD)
* [PHPerのための「2020年のPHP/Laravel振り返り+2021年」を語るTechCafe](https://hackmd.io/@hrxVDayfRGeTR-1JBV3QLA/H1dA4TGku)
* [PHPerのための「Laravel 入門を語り合う」PHP TechCafe
](https://hackmd.io/BKYlg2FKRVCdULZ0TNFG7w?both)
* [PHPerのための「2021年のPHP/Laravel振り返り+2022年」を語るTechCafe](https://hackmd.io/X8XLpiC7SEWsbW3kpfE4iA?view)
* [PHPerのための「Laravel 9 について語る」PHPTechCafe](https://hackmd.io/nYcZeh-9Rl-EtKdopnAhLQ?view)
* Laravel 10を入れるところまで手順をまとめる(加納)
* Native type declarations in Laravel 10 skeleton(廣部)
* [Release Note](https://laravel.com/docs/10.x/releases#types)
* DeepLでの日本語訳
> アプリケーションのスケルトンとスタブのタイプヒントは、Nuno Maduro氏によって提供されました。
>
> Laravelの最初のリリースでは、当時のPHPで利用可能なすべてのタイプヒントの機能を利用しました。しかし、その後、プリミティブ型ヒントの追加、戻り値の型、ユニオン型など、多くの新機能がPHPに追加されました。
> Laravel 10.xでは、アプリケーションスケルトンとフレームワークで利用されるすべてのスタブを徹底的に更新し、すべてのメソッド署名に引数と戻り値の型を導入しています。また、余計な「doc block」型ヒントの情報は削除されました。
* [わかりやすい日本語記事](https://biz.addisteria.com/laravel10/#toc3)
* 新しくひな型作ると、引数と戻り値に型宣言が追加されている
* 余計な「doc block」というのは「PHPDoc」のこと?
PHPDoc補足していた型ヒントが消えて、型宣言に置き換えたということか
* 下位互換性があるので、型宣言が追加されたと言って既存プロジェクトが動かなくなることはないらしい
* 型のない言語はもう許されない(流行らない)のか……?
*
* [Invokable Validation rules are the default](https://github.com/laravel/framework/pull/43868)(神山)
Laravel9で導入された[Invokable 検証ルール](https://github.com/laravel/framework/pull/42689)をデフォルトにする変更。
この変更によって得られるメリットは2点
- コードが簡潔になる
- コストがシンプルになった分、学習コストが減る
laravelは`php artisan make:rule [ルールのファイル名]`で独自のバリデーションルールを設定できる。
makeコマンドに引数が無い場合はpassesメソッドとmessageメソッドが実装されたコードが生成される
下記コードは[Github](https://github.com/laravel/framework/pull/42689)のもの
```php
class Quantity implements Rule
{
protected $messages = [];
public function passes($attribute, $value)
{
if (! is_array($value)) {
$this->messages[] = trans('validation.quantity.must_be_an_object');
return false;
}
if (! array_key_exists('magnitude', $value)) {
$this->messages[] = trans('validation.quantity.missing_magnitude');
}
if (! array_key_exists('units', $value)) {
$this->messages[] = trans('validation.quantity.missing_units');
}
return $this->messages === [];
}
public function message()
{
return $this->messages;
}
}
```
passesでバリデーションを実施してfalseであればmessageをreturnする。
上記のコードでいうと、配列のkeyに`'magnitude`が存在しない時、`validation.quantity.missing_magnitude`メッセージが返される。
makeコマンドの引数にinvokableを指定するとinvokeメソッドのみが実装されたシンプルなコードが生成される(invokable rule)。
`php artisan make:rule [ルールのファイル名] --invokable`
下記コードは[Github](https://github.com/laravel/framework/pull/42689)のもの
```php
class InvokableQuantity implements InvokableRule
{
public function __invoke($attribute, $value, $fail)
{
if (! is_array($value)) {
return $fail('validation.quantity.must_be_an_object')->translate();
}
if (! array_key_exists('magnitude', $value)) {
$fail('validation.quantity.missing_magnitude')->translate();
}
if (! array_key_exists('units', $value)) {
$fail('validation.quantity.missing_units')->translate();
}
}
}
```
invokeメソッドの引数`$fail`は失敗時に実行されるコールバック関数。
Laravel10からmake:ruleコマンドに引数invokableを渡さなくてもinvokable ruleが適用されるようになった。
なお呼び出し方はどちらも同じなので後方互換性が無くなることはない。
移行する場合もシンプルで以下のようにすればよい
1. Quantityクラスpasses内の下記のコードをInvokableQuantityクラスの__invoke関数内にコピペする
```php
public function passes($attribute, $value) {
中略...
if (! array_key_exists('units', $value)) {
$this->messages[] = trans('validation.quantity.missing_units');
}
}
```
↓
```php
public function __invoke($attribute, $value, $fail) {
if (! array_key_exists('units', $value)) {
$this->messages[] = trans('validation.quantity.missing_units');
}
}
```
2. messagesに値を入れている部分を$failを使用するように修正する。
```php
public function __invoke($attribute, $value, $fail) {
if (! array_key_exists('units', $value)) {
$fail('validation.quantity.missing_units')->translate();
}
}
```
* 非推奨前半(浅野)
- Remove various deprecations Pull Request #41136
- `getBaseQuery` の削除
- `Illuminate\Database\Eloquent\Relations\Relation`クラスの`getBaseQuery`メソッドの名前が`toBase`に変更されました
- `MaintenanceModeException` の削除
- `MaintenanceModeException`はアプリケーションがメンテナンスモードの時にステータスコード503で投げられる例外
- `MocksApplicationServices`
- https://github.com/laravel/framework/issues/41027
- [日本語記事](https://zenn.dev/at_yasu/articles/laravel-10-release#servicemock-%3A%3A-impact%3Amedium)
- Remove deprecated dates property in Pull Request #42587
- `Eloquent` モデルの非推奨の`$dates`プロパティが削除されました
- `$casts`プロパティを使用する必要があります。
- Remove handleDeprecation method in Pull Request #42590
- 非推奨のログを出力するメソッド
- `handleDeprecation` メソッドの削除
- 代わりに `handleDeprecationError` を使う
- https://laravel.com/api/9.x/Illuminate/Foundation/Bootstrap/HandleExceptions.html#method_handleDeprecation
* 非推奨後半(沼本)
* `assertTimesSent`メソッドが削除された。
* 通知が送信された回数の合計をassertするテスト用のメソッド。
* `assertSentTimes`メソッドを代わりに使用する。
* `ScheduleListCommand.php`の`$defaultName`プロパティが削除された。
* スケジュールされているタスクのリストを表示するコマンド。
* `$defaultName`プロパティは遅延ロード中にコマンドを識別するために使用されていた模様。([修正コミット](https://github.com/laravel/framework/commit/419471eb24563b7d8dd0fd307056b096076c9008))
* 使用する側には影響なしと思われる。
* `Route::home`メソッドが削除された。
* `home`として登録されているルートに遷移するメソッドのよう。
* `dispatchNow()`が削除された。
* ジョブをすぐに実行するメソッド。
* ジョブをすぐに実行したい場合は代わりに`dispatchSync()`を使用する必要がある。
## イベントの流れ
* Laravel 10を使ってみます
* 使う過程でLaravelの基本的な機能をおさらいします
* 過去資料の手順をもとに説明
* Laravel10を使って画面表示まで
* 変更点を触れるなら、その場で触る
## 参考資料
* [Laravel 公式](https://laravel.com/docs/10.x/releases)
* [Laravel News](https://laravel-news.com/laravel-10)
* [PHP Weekly News で紹介されていた記事](https://benjamincrozat.com/laravel-10)