spatie/once 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

spatie/once

Composer 安装命令:

composer require spatie/once

包简介

A magic memoization function

README 文档

README

Social Card of Once

A magic memoization function

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

This package contains a once function. You can pass a callable to it. Here's quick example:

$myClass = new class() {
    public function getNumber(): int
    {
        return once(function () {
            return rand(1, 10000);
        });
    }
};

No matter how many times you run $myClass->getNumber() inside the same request you'll always get the same number.

Are you a visual learner?

Under the hood, this package uses a PHP 8 Weakmap. In this video, you'll see what a weakmap is, together with a nice demo of the package.

Support us

We invest a lot of resources into creating best in class open source packages. You can support us by buying one of our paid products.

We highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using. You'll find our address on our contact page. We publish all received postcards on our virtual postcard wall.

Installation

You can install the package via composer:

composer require spatie/once

Usage

The once function accepts a callable.

$myClass = new class() {
    public function getNumber(): int
    {
        return once(function () {
            return rand(1, 10000);
        });
    }
};

No matter how many times you run $myClass->getNumber() you'll always get the same number.

The once function will only run once per combination of argument values the containing method receives.

class MyClass
{
    /**
     * It also works in static context!
     */
    public static function getNumberForLetter($letter)
    {
        return once(function () use ($letter) {
            return $letter . rand(1, 10000000);
        });
    }
}

So calling MyClass::getNumberForLetter('A') will always return the same result, but calling MyClass::getNumberForLetter('B') will return something else.

Flushing the cache

To flush the entire cache you can call:

Spatie\Once\Cache::getInstance()->flush();

Disabling the cache

In your tests you probably don't want to cache values. To disable the cache you can call:

Spatie\Once\Cache::getInstance()->disable();

You can re-enable the cache with

Spatie\Once\Cache::getInstance()->enable();

Octane compatibility

Warning

This behaviour is in beta and needs to be tested by the community. You can find this topic in discussion #79.

In order to have once working properly in an Octane environment, Cache::getInstance()->flush() must be called when OperationTerminated event is triggered. You can configure it in config/octane.php file:

// config/octane.php

OperationTerminated::class => [
    FlushTemporaryContainerInstances::class,
    // DisconnectFromDatabases::class,
    // CollectGarbage::class,

    FlushSpatieOnce::class, // we should create this class we have added here
],

And create the FlushSpatieOnce:class:

// app/Listeners/FlushSpatieOnce.php

use Spatie\Once\Cache;

class FlushSpatieOnce
{
    public function handle($event)
    {
        Cache::getInstance()->flush();
    }
}

Under the hood

The once function will execute the given callable and save the result in the $values property of Spatie\Once\Cache. This class is a singleton. When we detect that once has already run before, we're just going to return the value stored inside the $values weakmap instead of executing the callable again.

The first thing it does is calling debug_backtrace. We'll use the output to determine in which function and class once is called and to get access to the object that function is running in. Yeah, we're already in voodoo-land. The output of the debug_backtrace is passed to a new instance of Backtrace. That class is just a simple wrapper, so we can work more easily with the backtrace.

$trace = debug_backtrace(
    DEBUG_BACKTRACE_PROVIDE_OBJECT, 2
)[1];

$backtrace = new Backtrace($trace);

$object = $backtrace->getObject();

Next, we calculate a hash of the backtrace. This hash will be unique per function once was called in and the values of the arguments that function receives.

$hash = $backtrace->getHash();

Finally, we will check if there's already a value stored for the given hash. If not, then execute the given $callback and store the result in the weakmap of Spatie\Once\Cache. In the other case, we just return the value from that cache (the $callback isn't executed).

public function has(object $object, string $backtraceHash): bool
{
    if (! isset($this->values[$object])) {

        return false;
    }

    return array_key_exists($backtraceHash, $this->values[$object]);
}

Changelog

Please see CHANGELOG for more information what has changed recently.

Testing

composer test

Contributing

Please see CONTRIBUTING for details.

Security

If you've found a bug regarding security please mail security@spatie.be instead of using the issue tracker.

Credits

And a special thanks to Caneco for the logo ✨

Credit for the idea of the once function goes to Taylor Otwell. The code for this package is based upon the code he was kind enough to share with us.

License

The MIT License (MIT). Please see License File for more information.

spatie/once 适用场景与选型建议

spatie/once 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 29.82M 次下载、GitHub Stars 达 1.44k, 最近一次更新时间为 2016 年 11 月 06 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「cache」 「callable」 「memoization」 「spatie」 「once」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 spatie/once 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 spatie/once 我们能提供哪些服务?
定制开发 / 二次开发

基于 spatie/once 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 29.82M
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 1444
  • 点击次数: 26
  • 依赖项目数: 95
  • 推荐数: 0

GitHub 信息

  • Stars: 1437
  • Watchers: 9
  • Forks: 61
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2016-11-06