[扩展推荐] Laravel-model-caching 自动缓存模型及关联数据
起因
我创建这个包是为了满足一个客户的需求,该项目具有复杂的嵌套表单,其中包含许多 <select>
,导致在一个页面上有700多个数据库查询。我需要一个从模型中抽象缓存过程的包,可以缓存自定义查询以及缓存模型关系。本包试图满足这些需求。
特性
- 自运行、自失效关系(仅在渴求式加载时)缓存。
- 自运行、自失效模型查询缓存。
- 支持使用缓存标签。
要求
- PHP >= 7.1.3
- Laravel 5.8
可能冲突的包
任何覆盖 Model
类中的 newEloquentModel()
方法的包都可能与此包冲突。 当然,任何实现自己的 Querybuilder 类的包都会有效地绕过这个包,使它们不兼容。
以下是我们认为可能不兼容的包:
- grimzy/laravel-mysql-spatial
- fico7489/laravel-pivot
- chelout/laravel-relationship-events
- spatie/laravel-query-builder
- dwightwatson/rememberable
当前无效事项
以下情形目前使用本包无效。
- 延迟加载关系缓存,见#127。当前延迟加载的从属关系(belongs-to relationships)被缓存。其他关联关系的缓存工作正在进行中。
- 在有 Eloquent 查询中使用 select() 子句,参见 #238 (在问题中讨论的变通方法)
Installation
请确保不需要此软件包的特定版本时,这样使用:
composer require genealabs/laravel-model-caching:*
更新说明
0.6.0
用于禁用此包的环境和配置项已更改。
-
如果你之前已发布配置文件,请再次发布,并根据需要进行调整:
php artisan modelCache:publish --config
-
如果你在 .env 文件中禁用了包,请将
MODEL_CACHE_DISABLED
更改为true
。
0.5.0
以下接口已更改(请参阅下面的相应部分):
- 指定模型的缓存前缀
配置
推荐(可选)自定义缓存存储
如果你要使用与 Laravel 默认缓存存储不同的缓存存储,你可以通过将 .env
文件中的 MODEL_CACHE_STORE
环境变量设置为 config/cache.php
中配置的缓存存储的名称来实现(你可以根据你的特定需求定义任何自定义缓存存储)。
MODEL_CACHE_STORE=redis2
使用
为获得最佳性能,建议使用可标记的缓存存储(如 redis、memcached)。虽然这是可选的,但使用不可标记的缓存存储意味着每次创建、保存、更新或删除模型时都会清除整个缓存。
为了便于维护,我建议添加一个使用了 Cachable
trait 的 BaseModel
模型,从中扩展所有其他的模型。 如果你不想这样做,只需直接从 CachedModel
扩展你的模型。
以下是 BaseModel
类的示例:
<?php namespace App;
use GeneaLabs\LaravelModelCaching\Traits\Cachable;
abstract class BaseModel
{
use Cachable;
//
}
多数据库连接
感谢 @dtvmedia 对这个特性的建议。这实际上是一个比 cache 前缀更健壮的解决方案
多个数据库连接会自动处理(译者注 确保不同连接缓存键前缀不一样)键独立。这对于多应用程序尤其重要,当然对于任何使用多个数据库连接的应用程序也是如此。
可选的缓存键前缀
感谢 @lucian-dragomir 推荐这个特性 !您可以使用缓存键前缀来为多个应用程序维护各自缓存条目。为此,建议将可缓存特性添加到基本模型中,然后在那里设置缓存键前缀配置值。
示例:
<?php namespace GeneaLabs\LaravelModelCaching\Tests\Fixtures;
use GeneaLabs\LaravelModelCaching\Traits\Cachable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
class BaseModel extends Model
{
use Cachable;
protected $cachePrefix = "test-prefix";
}
还可以在配置文件为所有缓存的模型设置缓存前缀:
'cache-prefix' => 'test-prefix',
例外: 用户模型
我不建议缓存用户模型,因为这是一种特殊情况,这是由于它扩展了 lighting \Foundation\Auth\User
。重写它会破坏(既有)功能。不仅如此,缓存用户模型可能也不是一个好主意,因为您总是希望从中提取最新的信息。
实验特性: 在特定模型中使用缓存 Cool-down (冷却期)
在某些情况下,您可能希望添加缓存失效冷却期。例如,您可能有一个繁忙的站点,其中评论以很高的速率提交,并且您不希望每次提交的评论都使缓存失效。虽然我不推荐这样做,但您可以试验一下它的有效性。
要使用它,必须在模型(或基础模型,如果你想在多个或所有模型上使用它)中启用:
class MyModel extends Model
{
use Cachable;
protected $cacheCooldownSeconds = 300; // 单位秒 5 分钟
// ...
}
之后可以在查询中(这样)实现:
(new Comment)
->withCacheCooldownSeconds(30) // 重写模型中默认的 cooldown ( 即属性$cacheCooldownSeconds)秒数
->get();
或:
(new Comment)
->withCacheCooldownSeconds() // 使用模型中默认的cooldown秒数
->get();
禁用查询缓存
有两种方法可以禁用模型缓存:
- 在逐个查询实例中使用
->disableCache()
。 - 在
.env
文件中将MODEL_CACHE_DISABLED
设为true
。 -
如果你只需要为代码块或非 Eloquent 查询禁用缓存,这可能是更好的选择:
$result = app("model-cache")->runDisabled(function () { return (new MyModel)->get(); // or any other stuff you need to run with model-caching disabled });
建议:在所有填充查询中使用 #1 选项,以避免在重新填充多次时提取了缓存信息。 你可以在链式查询中的任何位置使用 disableCache()
来禁用给定查询。 例如:
$results = $myModel->disableCache()->where('field', $value)->get();
手动刷新特定模型
你可以使用这条 Artisan 命令刷新特定模型的缓存:
php artisan modelCache:clear --model=App\Model
手动更新数据库时,这条命令就会排上用场。当 Laravel 应用之外的来源更新数据库后,也可以触发此操作。
总结
这就是你需要做的。现在缓存了所有模型查询和(关联)关系!!
在已经优化了一些页面的性能测试,高达900%! 大多数情况下,您应该看到性能提高了100%左右。
质量承诺
在包开发期,我尽可能地采用好的设计和开发实践,以确保这个包是最好的。我的软件包开发清单包括:
- ✅ 实现尽可能接近100%的代码覆盖率进行单元测试。
- ✅ 消除由Sensiolabs Insight 和 Scrunizer 发现的任何问题。
- ✅ 完全兼容PSR1、PSR2 PSR4
- ✅ 在 README.md 文件内包含详实文档。
- ✅ 提供一个最新的 CHANGELOG.md 更新日志,日志遵从https://keepachangelog.com 规范。
- ✅ 所有代码无 PHPMD 或 PHPCS 警告。
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
哇,这个不错哎
老版本 用不了吧
9.x 好像不兼容