jessegall / laravel-memoize
Requires
- laravel/framework: ^10.0|^11.0
Requires (Dev)
- orchestra/testbench: ^8.26
README
Laravel Memoize 是一个库,它为 Laravel Eloquent 模型和其他 PHP 类提供了方法级别的缓存。它通过根据方法的参数缓存方法调用的结果来提高性能。
记忆化
记忆化是一种技术,用于缓存函数调用的结果,并在相同的输入再次发生时返回缓存的结果。
特性
- 使用简单的特质易于实现
- 与 Eloquent 模型和常规 PHP 类兼容
- 支持基于方法参数的缓存
- 同一模型的多个实例共享缓存
- 在模型更新(或自定义事件)时自动使缓存失效
- 可自定义不同存储选项的缓存驱动程序
- 可自定义参数序列化以实现细粒度控制
目录
安装
您可以通过 Composer 安装此包
composer require jessegall/laravel-memoize
使用
- 在您的 Eloquent 模型或 PHP 类中使用
Memoize
特质
use JesseGall\LaravelMemoize\Memoize; class YourModel extends Model { use Memoize; // ... your model code }
- 使用
memoize
函数包装您想记忆化的逻辑
public function expensiveCalculation($param1, $param2) { return $this->memoize(function() use ($param1, $param2) { // Your expensive calculation here // For example: // - Complex database queries // - API calls // - Resource-intensive computations $result = // ... return $result; }); }
基于提供给调用 memoize
的方法的参数记忆化回调的结果。在本例中,expensiveCalculation
的结果根据 $param1
和 $param2
的值进行缓存。
记忆化与模型
当使用 Laravel Memoize 与 Eloquent 模型一起使用时,它的工作方式如下
- 如果在模型中使用
Memoize
特质,记忆化将与模型的 ID(主键)相关联。 - 如果将模型作为参数传递给记忆化方法,则模型的 ID 将用作缓存键的一部分。
这意味着
- 同一模型的实例(相同 ID)将共享相同的记忆化结果。
- 新查询的模型将使用可用的现有缓存结果。
以下是实际应用中的示例
class User extends Model { use Memoize; public function expensiveCalculation() { return $this->memoize(function() { // Expensive operation here... return $result; }); } } // Using Memoize in a model $user1 = User::find(1); $result1 = $user1->expensiveCalculation(); $user2 = User::find(1); // Different instance, same ID $result2 = $user2->expensiveCalculation(); // $result1 and $result2 are the same, calculation done only once // Passing a model as an argument class Calculator { use Memoize; public function complexCalculation(User $user) { return $this->memoize(function() use ($user) { // Complex calculation return $result; }); } } $calculator = new Calculator(); // $result3 and $result4 are the same, calculation done only once $result3 = $calculator->complexCalculation($user1); $result4 = $calculator->complexCalculation($user2);
记忆化驱动程序
Laravel Memoize 可以使用不同的驱动程序来存储缓存结果。它自带两个内置驱动程序:MemoryDriver
和 CacheDriver
。
可用驱动程序
-
MemoryDriver(默认):将缓存结果存储在内存中,直到请求结束。
-
CacheDriver:利用 Laravel 的缓存系统来存储记忆化结果。这允许结果在不同的请求之间持久化,并在连接到同一缓存存储的多台服务器之间共享。
⚠️ 针对 Laravel Octane 用户的重要通知
当与 MemoryDriver
一起使用 Laravel Octane 时,请注意,记忆化结果会跨由同一工作者处理的多个请求持久化。这可以提高性能,但也可能导致提供过时的数据。对于经常变化的数据,请实现适当的缓存清除机制以确保其新鲜性。
使用驱动程序
默认情况下,Laravel Memoize 使用 MemoryDriver
。要使用不同的驱动程序,请覆盖模型或类中的 memoizeDriver
方法
use JesseGall\LaravelMemoize\Drivers\CacheDriver; use JesseGall\LaravelMemoize\Drivers\DriverInterface; class YourModel extends Model { use Memoize; public static function memoizeDriver(): DriverInterface { return new CacheDriver(ttl: 60); // Cache results for 60 seconds } }
创建自定义驱动程序
您可以通过实现 DriverInterface
创建自己的自定义驱动程序
- 创建自定义驱动类
use JesseGall\LaravelMemoize\Drivers\DriverInterface; class CustomDriver implements DriverInterface { // Implement the required methods }
- 在您的模型或类中使用自定义驱动
class YourModel extends Model { use Memoize; public static function memoizeDriver(): DriverInterface { return new CustomDriver(); } }
动态切换驱动程序
您可以基于特定条件动态切换驱动
class YourModel extends Model { use Memoize; public static function memoizeDriver(): DriverInterface { if (config('app.env') === 'production') { return new CacheDriver(); } return new MemoryDriver(); } }
参数序列化
Laravel Memoize 使用参数序列化器生成基于方法参数的唯一缓存键。您可以通过覆盖默认的 ArgumentSerializerFactoryInterface
或创建自己的 ArgumentSerializerFactoryInterface
实现来自定义此行为。
覆盖默认工厂
要覆盖默认的参数序列化器工厂,您可以在应用程序服务提供者中将您的自定义实现绑定到 ArgumentSerializerFactoryInterface
use App\Services\CustomArgumentSerializer; use JesseGall\LaravelMemoize\ArgumentSerializerFactoryInterface; class AppServiceProvider extends ServiceProvider { public function register() { $this->app->bind(ArgumentSerializerFactoryInterface::class, CustomArgumentSerializerFactory::class); } }
扩展默认工厂
如果您想扩展默认的 ArgumentSerializerFactory
以支持额外的类型或修改现有的序列化逻辑,您可以创建一个扩展 ArgumentSerializerFactory
的新类
use JesseGall\LaravelMemoize\ArgumentSerializerFactory; use JesseGall\LaravelMemoize\Serializers\Serializer; use App\Models\CustomModel; use App\Services\CustomModelSerializer; class ExtendedArgumentSerializerFactory extends ArgumentSerializerFactory { public function make(mixed $arg): SerializerInterface { if ($arg instanceof CustomModel) { return new CustomModelSerializer(); } return parent::make($arg); } }
然后,在应用程序服务提供者中绑定您的扩展序列化器
use JesseGall\LaravelMemoize\ArgumentSerializerFactoryInterface; class AppServiceProvider extends ServiceProvider { public function register() { $this->app->bind(ArgumentSerializerFactoryInterface::class, ExtendedArgumentSerializerFactory::class); } }
通过自定义参数序列化器,您可以控制不同类型的参数在生成缓存键时的序列化方式,从而对记忆过程有更细粒度的控制。
缓存
清除缓存
要手动清除特定实例的缓存
$model->memoizeForget();
自定义缓存失效事件
默认情况下,当模型被 '保存' 或删除时,模型的缓存会自动清除。您可以通过覆盖 memoizeCacheInvalidationEvents
方法来自定义触发缓存无效化的事件
class User extends Model { use Memoize; public static function memoizeCacheInvalidationEvents(): array { return ['saved', 'deleted', 'custom-event']; } // ... }
测试
要运行测试,请使用以下命令
vendor/bin/phpunit
贡献
欢迎贡献!请随时提交 Pull Request。
许可
此软件包是开源软件,采用 MIT 许可证 许可。