spatie / once
一个神奇的记忆化函数
Requires
- php: ^8.0
Requires (Dev)
- pestphp/pest: ^1.21
- symfony/var-dumper: ^5.1
README
一个神奇的 记忆化 函数
此包包含一个 once
函数。您可以向其传递一个 callable
。以下是一个快速示例
$myClass = new class() { public function getNumber(): int { return once(function () { return rand(1, 10000); }); } };
无论您在同一个请求中运行多少次 $myClass->getNumber()
,您总会得到同一个数字。
您是视觉学习者吗?
在内部,此包使用 PHP 8 Weakmap。在 此视频中,您将了解弱map是什么,以及该包的一个很好的演示。
支持我们
我们投入了大量资源来创建 一流的开放源代码包。您可以通过 购买我们的付费产品之一 来支持我们。
我们非常感谢您从您的家乡给我们寄明信片,提到您正在使用我们的哪个包。您可以在 我们的联系页面 上找到我们的地址。我们在 我们的虚拟明信片墙 上公布所有收到的明信片。
安装
您可以通过 composer 安装此包
composer require spatie/once
用法
once
函数接受一个 callable
。
$myClass = new class() { public function getNumber(): int { return once(function () { return rand(1, 10000); }); } };
无论您运行多少次 $myClass->getNumber()
,您总会得到同一个数字。
once
函数只会运行一次,每个包含方法接收到的参数值的组合。
class MyClass { /** * It also works in static context! */ public static function getNumberForLetter($letter) { return once(function () use ($letter) { return $letter . rand(1, 10000000); }); } }
因此,调用 MyClass::getNumberForLetter('A')
总是返回相同的结果,但调用 MyClass::getNumberForLetter('B')
将返回不同的结果。
刷新缓存
要刷新整个缓存,您可以调用
Spatie\Once\Cache::getInstance()->flush();
禁用缓存
在您的测试中,您可能不想缓存值。要禁用缓存,您可以调用
Spatie\Once\Cache::getInstance()->disable();
您可以使用以下方法重新启用缓存
Spatie\Once\Cache::getInstance()->enable();
Octane 兼容性
警告
此行为处于测试阶段,需要社区测试。您可以在 讨论 #79 中找到此主题。
为了使 once
在 Octane 环境中正常工作,必须在触发 OperationTerminated
事件时调用 Cache::getInstance()->flush()
。您可以在 config/octane.php
文件中配置它
// config/octane.php OperationTerminated::class => [ FlushTemporaryContainerInstances::class, // DisconnectFromDatabases::class, // CollectGarbage::class, FlushSpatieOnce::class, // we should create this class we have added here ],
并创建 FlushSpatieOnce:class
// app/Listeners/FlushSpatieOnce.php use Spatie\Once\Cache; class FlushSpatieOnce { public function handle($event) { Cache::getInstance()->flush(); } }
在内部
once
函数将执行给定的可调用函数并将结果保存到 Spatie\Once\Cache
的 $values
属性中。此类 是一个单例。当我们检测到 once
已运行过时,我们将直接返回存储在 的 $values
weakmap 中的值,而不是再次执行可调用函数。
它首先调用 debug_backtrace
。我们将使用输出结果来确定 once
在哪个函数和类中被调用,以及访问运行该函数的 object
。是的,我们已经在巫术领域了。 debug_backtrace
的输出被传递给一个新实例的 Backtrace
。这个类只是一个简单的包装器,这样我们就可以更容易地处理回溯。
$trace = debug_backtrace( DEBUG_BACKTRACE_PROVIDE_OBJECT, 2 )[1]; $backtrace = new Backtrace($trace); $object = $backtrace->getObject();
接下来,我们计算回溯的 hash
。这个 hash 将在每个 once
被调用的函数及其接收到的参数值中是唯一的。
$hash = $backtrace->getHash();
最后,我们将检查是否已经为给定的 hash 存储了值。如果没有,则执行给定的 $callback
并将结果存储在 Spatie\Once\Cache
的弱映射中。在另一种情况下,我们只需从缓存中返回该值($callback
不会被执行)。
public function has(object $object, string $backtraceHash): bool { if (! isset($this->values[$object])) { return false; } return array_key_exists($backtraceHash, $this->values[$object]); }
更新日志
请参阅 更新日志 了解最近的变化。
测试
composer test
贡献
请参阅 贡献指南 了解详细信息。
安全性
如果您发现有关安全性的错误,请通过邮件 [email protected] 联系我们,而不是使用问题跟踪器。
鸣谢
特别感谢 Caneco 为我们设计的标志 ✨
关于 once
函数的想法归功于 Taylor Otwell。这个包的代码基于他慷慨分享的代码。
许可证
MIT 许可证 (MIT)。有关更多信息,请参阅 许可证文件。