once()
函数最初的灵感来自 Taylor Otwell 的这条推特,由 Spatie 制作成 包,现在它成为了 Laravel 框架核心的一部分,在 Laravel 11 中。
此助手可确保无论您调用对象方法多少次,始终获得相同的值。当您有一些代码希望确保只执行一次时,once 函数非常有用。
让我们使用新的 Laravel 11 make:class
Artisan 命令来演示它的工作原理
php artisan make:class OnceDemo
以下是演示记忆化工作原理的 OnceDemo
代码
<?php namespace App; use Illuminate\Support\Str;use Ramsey\Uuid\UuidInterface; class OnceDemo{ public function uuid(): UuidInterface { return Str::uuid(); } public function uuidOnce(): UuidInterface { return once(fn (): UuidInterface => $this->uuid()); }}
如果您在不使用 once()
助手的情况下运行以下 PHP 代码,您将在每次方法调用时都会得到一个新的 UUID
$demo = new App\OnceDemo; foreach (range(1,5) as $_) { echo $demo->uuid() . "\n";} /*9ee5dc3c-f34b-4424-827d-13b662bb0ce1ad9cca9d-4e98-4307-994c-c610df7c70acd642bc9e-d8bb-4bfe-a647-78b555b22e1c7968b5f2-80f4-40de-95e0-e1f576c37e6078b69cbb-07b3-45a4-b77b-edefb16f2782*/
但是,如果您使用 once()
助手运行相同的代码,您将每次都得到相同的结果
$demo = new App\OnceDemo; foreach (range(1,5) as $_) { echo $demo->uuidOnce() . "\n";} /*5cdfa44b-5ae5-4b0f-8a6f-4b167307fa055cdfa44b-5ae5-4b0f-8a6f-4b167307fa055cdfa44b-5ae5-4b0f-8a6f-4b167307fa055cdfa44b-5ae5-4b0f-8a6f-4b167307fa055cdfa44b-5ae5-4b0f-8a6f-4b167307fa05*/
此方法将在我们的演示示例中始终返回相同的对象实例,您可以验证此行为
$demo = new App\OnceDemo; foreach (range(1,5) as $_) { echo spl_object_id($demo->uuidOnce()) . "\n";} /*50755075507550755075*/
在运行测试时,必须在每次测试后清除记忆化函数,以确保您处于原始状态。Laravel 在基本 TestCase
类中使用 Once::flush();
方法为您处理此细节。
感谢 Nuno Maduro,他在 Pull Request #49744 中实现了此功能!