spatie/once

一个神奇的记忆化函数

维护者

详细信息

github.com/spatie/once

主页

源代码

安装次数: 23,352,809

依赖者: 83

推荐者: 0

安全性: 0

星标: 1,253

关注者: 10

分支: 57

3.1.1 2024-05-27 09:17 UTC

README

Social Card of Once

一个神奇的 记忆化 函数

Latest Version on Packagist Software License Build Status Quality Score StyleCI Total Downloads

此包包含一个 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)。有关更多信息,请参阅 许可证文件