PHP8.1の「第一級callableを生成する記法」を使うコードの書き換え例 ==== https://www.php.net/manual/ja/functions.first_class_callable_syntax.php Laravelを使っていると複雑なクロージャを並べることがよくある。これを整理したい時に使える。 ```php use App\Models\Post; use Illuminate\Contracts\Database\Query\Builder; public function index() { $posts = Post::query() ->where(function (Builder $query) { $query->where('name', 'test') ->where('foo', 'foo'); })->where(function (Builder $query) { $query->where('title', 'test') ->where('bar', 'bar'); })->get(); } ``` まずクロージャをメソッドに分けて`Closure::fromCallable`でcallableからクロージャに変換。PHP8.0まではこの書き方。 ```php use App\Models\Post; use Closure; use Illuminate\Contracts\Database\Query\Builder; public function index() { $posts = Post::query() ->where(Closure::fromCallable([$this, 'name'])) ->where(Closure::fromCallable([$this, 'title'])) ->get(); } private function name(Builder $query): void { $query->where('name', 'test') ->where('foo', 'foo'); } private function title(Builder $query): void { $query->where('title', 'test') ->where('bar', 'bar'); } ``` PHP8.1の「第一級callableを生成する記法」は`Closure::fromCallable`とほぼ同じなのでそのまま書き換えられる。 ```php use App\Models\Post; use Illuminate\Contracts\Database\Query\Builder; public function index() { $posts = Post::query() ->where($this->name(...)) ->where($this->title(...)) ->get(); } private function name(Builder $query): void { $query->where('name', 'test') ->where('foo', 'foo'); } private function title(Builder $query): void { $query->where('title', 'test') ->where('bar', 'bar'); } ``` PhpStormならインテンションアクションに出てくるので自分で書き換えなくても自動で置換できる。 新しい記法の`(...)`に慣れない場合は`Closure::fromCallable`で書いてPhpStormに書き換えて貰えばいい。 まだ定着してないのでいきなり新記法で書くことはなくとりあえずクロージャで書いたコードを後から書き換える使い方がほとんど。