Twinkle

Twinkle

PHP8.1の「第一級callableを生成する記法」を使うコードの書き換え例

https://www.php.net/manual/ja/functions.first_class_callable_syntax.php

Laravelを使っていると複雑なクロージャを並べることがよくある。これを整理したい時に使える。

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まではこの書き方。

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とほぼ同じなのでそのまま書き換えられる。

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に書き換えて貰えばいい。

まだ定着してないのでいきなり新記法で書くことはなくとりあえずクロージャで書いたコードを後から書き換える使い方がほとんど。