taitava/php-cachedcall

这是一个简单的PHP特质,它使得在单个会话中缓存类方法调用结果变得容易。

1.1.0 2021-01-24 14:51 UTC

This package is auto-updated.

Last update: 2024-09-24 23:39:58 UTC


README

这是一个简单的PHP特质,它使得在单个会话中缓存类方法调用结果变得容易。

适用于

  • 缓存类方法调用。使用类私有属性进行缓存。
  • 一个易于应用到您自己类中的特质。
  • 简单而简洁 - 您只需几分钟就可以阅读和理解源代码,因此无需购买“猪在袋子里”。 :)

不适用于

  • 不能用于在会话之间持久存储缓存。 在您的程序完成后,缓存将会消失。
  • 由于特质设计,对类外函数进行缓存没有意义。但如果有需要,以后可以改进。

安装

使用composer

composer require "taitava/php-cachedcall:*"

然后在您的php应用程序中包含自动加载器

require_once "vendor/autoload.php";

用法

假设您有一个类 Page,如下所示

require_once "vendor/autoload.php";

class Page
{
  public $template = "page_template.html";
  public $title;
  public $author;
  public $content;
  public $date;

  public function __construct($data)
  {
    foreach ($data as $key => $value)
    {
      $this->$key = $value;
    }
  }

  public static function getPageFromDB($id)
  {
    $data = ORM::table("Page")->getById($id); // ORM class is not defined in this example, but let's just pretend that it exists. :)
    return new self($data);
  }

  public function RenderContent()
  {
    $template = file_get_contents($this->template);
    $data = [
      $this->title,
      $this->author,
      $this->content,
      $this->date,
    ];
    // ...
    // Do some placeholder replacements to $template with $data here...
    // ...
    return $template
  }
}

因此我们有两个方法(加上一个构造函数),我们希望缓存这两个方法,以避免在方法被多次调用时重复执行代码。我们的代码变为这样

require_once "vendor/autoload.php";

class Page
{
  use Taitava\CachedCall\CachedCallTrait; // Apply the trait for this class.

  public $template = "page_template.html";
  public $title;
  public $author;
  public $content;
  public $date;

  public function __construct($data)
  {
    foreach ($data as $key => $value)
    {
      $this->$key = $value;
    }
  }

  public static function getPageFromDB($id)
  {
    return static::cached_static_call(__METHOD__, func_get_args(), function ($id)
    {
      $data = ORM::table("Page")->getById($id); // ORM class is not defined in this example, but let's just pretend that it exists. :)
      return new self($data);
     });
  }

  public function renderContent()
  {
    return $this->cached_call(__METHOD__, func_get_args() /* Actually this is an empty array because this method has no parameters. */, function ()
    {
      $template = file_get_contents($this->template);
      $data = [
        $this->title,
        $this->author,
        $this->content,
        $this->date,
      ];
      // ...
      // Do some placeholder replacements to $template with $data here...
      // ...
      return $template
    });
  }
}

getPageFromDB() 是一个接受 $id 参数的静态方法。 renderContent() 方法是非静态的。在缓存非静态方法时,您应该调用 $this->cached_call() 方法,而在静态方法中,您应该调用 self::cached_static_call() 方法(或 static::cached_static_call())。记住,在需要时在中间添加 _static_ 字词!

cached_call()cached_static_call() 都有一组相似的参数

  • string $method_name:从其中调用 cached_call()/cached_static_call() 的方法的名称。您可以使用 __METHOD__。缓存键的一部分。
  • array $parameters:您想要传递给 $call 函数的任何参数。也将是缓存键的一部分。如果您不需要以任何方式更改参数,请使用 func_get_args()
  • callable $call:如果未找到具有匹配 $method_name+$parameters 缓存键的缓存,将调用的函数。

关于 $parameters 的限制

请注意,$parameters 只能包含

  • 标量值:数字、字符串、布尔值。
  • 具有可识别标识符字段的对象:$ID$id$Id$iD

以下是不接受的

  • 数组
  • 没有识别id属性的对象
  • 资源
  • 我忘记列出的事物

此限制存在,因为生成缓存键需要是一个快速的过程,并且难以定义一个可靠的缓存键,例如,对于内容可以在方法调用之间变化的大数组。此外,由于对象需要具有id属性,因此对象支持相当有限。不支持 id()getId() 方法。所有限制都可以在以后进行改进,如果想到更好的缓存键生成方式。

为了克服一些限制,例如,您可以绕过数组参数如下

require_once "vendor/autoload.php";

class Page
{
  use Taitava\CachedCall\CachedCallTrait; // Apply the trait for this class.

  public $template = "page_template.html";
  public $title;
  public $author;
  public $content;
  public $date;

  // ...

  public function doSomething(array $an_array)
  {
    $stringified_array = implode(",", $an_array); // Create a custom cache key. This can be done IF we know that the array is likely to be *small*. Be careful!
    $parameters = [$stringified_array];
    return $this->cached_call(__METHOD__, $parameters, function () use ($an_array)
    {
      // ...
      // Do something with $an_array...
      // ...
      return $result
    });
  }
}

注意,我们避免了将 $an_array 传递给 cached_call(),但我们通过 use ($an_array) 语句将其传递给我们的闭包函数!因此,我们能够在原始形式中使用该数组。

临时禁用缓存

如果您需要快速测试您的类而不使用缓存,您可以更改以下属性

require_once "vendor/autoload.php";

class Page
{
  use Taitava\CachedCall\CachedCallTrait;

  public function method1($parameter)
  {
    $this->enable_cached_calls = false; // Disable cache
    $result = $this->cached_call(__METHOD__, func_get_args(), function ()
    {
      // ...
      // Do something...
      // ...
      return $result
    });
    $this->enable_cached_calls = true; // Re-enable cache
    return $result;
  }

  public static function method2($parameter)
  {
    static::$enable_cached_static_calls = false; // Disable cache
    $result = $this->cached_call(__METHOD__, func_get_args(), function ()
    {
      // ...
      // Do something...
      // ...
      return $result
    });
    static::$enable_cached_static_calls = true; // Re-enable cache
  }
}

贡献

想法、错误报告和修复和新功能的拉取请求都是受欢迎的 :).

作者

Jarkko Linnanvirta