miradnan/laravel-model-caching
Composer 安装命令:
composer require miradnan/laravel-model-caching
包简介
Adding cache for Laravel Eloquent queries
README 文档
README
Laravel Query & Table Cache. This package helps adding caching to queries and tables at model level. It directly runs at Eloquent level, making use of cache before retrieving the data from the DB.
This package adds caching support for all query methods.
$ composer require miradnan/laravel-model-caching
Each model that will accept query-by-query caching will have to use the miradnan\QueryCache\Traits\QueryCacheable trait.
use miradnan\QueryCache\Traits\QueryCacheable; class Post extends Model { use QueryCacheable; ... }
use miradnan\QueryCache\Traits\TableCacheable; class Country extends Model { use TableCacheable; ... }
Showcase
Query Cache has the ability to track the SQL used and use it as a key in the cache storage, making the caching query-by-query a breeze.
use miradnan\QueryCache\Traits\QueryCacheable; class Article extends Model { use QueryCacheable; public $cacheFor = 3600; ... } // SELECT * FROM articles ORDER BY created_at DESC LIMIT 1; $latestArticle = Article::latest()->first(); // SELECT * FROM articles WHERE published = 1; $publishedArticles = Article::wherePublished(true)->get();
In the above example, both queries have different keys in the cache storage, thus it doesn't matter what query we handle. By default, caching is disabled unless specifying a value for $cacheFor. As long as $cacheFor is existent and is greater than 0, all queries will be cached.
It is also possible to enable caching for specific queries. This is the recommended way because it is easier to manage each query.
$postsCount = Post::cacheFor(60 * 60)->count(); // Using a DateTime instance like Carbon works perfectly fine! $postsCount = Post::cacheFor(now()->addDays(1))->count();
Cache Tags & Cache Invalidation
Some caching stores accept tags. This is really useful if you plan on tagging your cached queries and invalidate only some of the queries when needed.
$shelfOneBooks = Book::whereShelf(1)->cacheFor(60)->cacheTags(['shelf:1'])->get(); $shelfTwoBooks = Book::whereShelf(2)->cacheFor(60)->cacheTags(['shelf:2'])->get(); // After flushing the cache for shelf:1, the query of$shelfTwoBooks will still hit the cache if re-called again. Book::flushQueryCache(['shelf:1']); // Flushing also works for both tags, invalidating them both, not just the one tagged with shelf:1 Book::flushQueryCache(['shelf:1', 'shelf:2']);
Be careful tho - specifying cache tags does not change the behaviour of key storage. For example, the following two queries, altough the use the same tag, they have different keys stored in the caching database.
$alice = Kid::whereName('Alice')->cacheFor(60)->cacheTags(['kids'])->first(); $bob = Kid::whereName('Bob')->cacheFor(60)->cacheTags(['kids'])->first();
Relationship Caching
Relationships are just another queries. They can be intercepted and modified before the database is hit with the query. The following example needs the Order model (or the model associated with the orders relationship) to include the QueryCacheable trait.
$user = User::with(['orders' => function ($query) { return $query->cacheFor(60 * 60)->cacheTags(['my:orders']); }])->get(); // This comes from the cache if existed. $orders = $user->orders;
Cache Keys
The package automatically generate the keys needed to store the data in the cache store. However, prefixing them might be useful if the cache store is used by other applications and/or models and you want to manage the keys better to avoid collisions.
$bob = Kid::whereName('Bob')->cacheFor(60)->cachePrefix('kids_')->first();
If no prefix is specified, the string leqc is going to be used.
Cache Drivers
By default, the trait uses the default cache driver. If you want to force a specific one, you can do so by calling cacheDriver():
$bob = Kid::whereName('Bob')->cacheFor(60)->cacheDriver('dynamodb')->first();
Disable caching
If you enabled caching (either by model variable or by the cacheFor scope), you can also opt to disable it mid-builder.
$uncachedBooks = Book::dontCache()->get(); $uncachedBooks = Book::doNotCache()->get(); // same thing
Equivalent Methods and Variables
You can use the methods provided in this documentation query-by-query, or you can set defaults for each one in the model; using the methods query-by-query will overwrite the defaults.
While settings defaults is not mandatory (excepting for $cacheFor that will enable caching on all queries), it can be useful to avoid using the chained methods on each query.
class Book extends Model { public $cacheFor = 3600; // equivalent of ->cacheFor(3600) public $cacheTags = ['books']; // equivalent of ->cacheTags(['books']) public $cachePrefix = 'books_' // equivalent of ->cachePrefix('books_'); public $cacheDriver = 'dynamodb'; // equivalent of ->cacheDriver('dynamodb'); }
Implement the caching method to your own Builder class
Since this package modifies the newBaseQueryBuilder() in the model, having multiple traits that
modify this function will lead to an overlap.
This can happen in case you are creating your own Builder class for another database drivers or simply to ease out your app query builder for more flexibility.
To solve this, all you have to do is to add the \miradnan\QueryCache\Traits\QueryCacheModule trait and the \miradnan\QueryCache\Contracts\QueryCacheModuleInterface interface to your Builder class. Make sure that the model will no longer use the original QueryCacheable trait.
use miradnan\QueryCache\Traits\QueryCacheModule; use Illuminate\Database\Query\Builder as BaseBuilder; // the base laravel builder use miradnan\QueryCache\Contracts\QueryCacheModuleInterface; // MyCustomBuilder.php class MyCustomBuilder implements QueryCacheModuleInterface { use QueryCacheModule; // the rest of the logic here. } // MyBuilderTrait.php trait MyBuilderTrait { protected function newBaseQueryBuilder() { return new MyCustomBuilder( // ); } } // app/CustomModel.php class CustomModel extends Model { use MyBuilderTrait; } CustomModel::cacheFor(30)->customGetMethod();
Generating your own key
This is how the default key generation function looks like:
public function generatePlainCacheKey(string $method = 'get', $id = null, $appends = null): string { $name = $this->connection->getName(); // Count has no Sql, that's why it can't be used ->toSql() if ($method === 'count') { return $name.$method.$id.serialize($this->getBindings()).$appends; } return $name.$method.$id.$this->toSql().serialize($this->getBindings()).$appends; }
In some cases, like implementing your own Builder for MongoDB for example, you might not want to use the toSql() and use your own
method of generating per-sql key. You can do so by overwriting the MyCustomBuilder class generatePlainCacheKey() with your own one.
It is, however, highly recommended to use the most of the variables provided by the function to avoid cache overlapping issues.
class MyCustomBuilder implements QueryCacheModuleInterface { use QueryCacheModule; public function generatePlainCacheKey(string $method = 'get', $id = null, $appends = null): string { $name = $this->connection->getName(); // Using ->myCustomSqlString() instead of ->toSql() return $name.$method.$id.$this->myCustomSqlString().serialize($this->getBindings()).$appends; } }
Implementing cache for other functions than get()
Since all of the Laravel Eloquent functions are based on it, the builder that comes with this package replaces only the get() one:
class Builder { public function get($columns = ['*']) { if (! $this->shouldAvoidCache()) { return $this->getFromQueryCache('get', $columns); } return parent::get($columns); } }
In case that you want to cache your own methods from your custom builder or, for instance, your count() method doesn't rely on get(), you can replace it using this syntax:
class MyCustomBuilder { public function count() { if (! $this->shouldAvoidCache()) { return $this->getFromQueryCache('count'); } return parent::count(); } }
In fact, you can also replace any eloquent method within your builder if you use $this->shouldAvoidCache() check and retrieve the cached data using getFromQueryCache() method, passing the method name as string, and, optionally, an array of columns that defaults to ['*'].
Notice that the getFromQueryCache() method accepts a method name and a $columns parameter. If your method doesn't implement the $columns, don't pass it.
Note that some functions like getQueryCacheCallback() may come with an $id parameter.
The default behaviour of the package doesn't use it, since the query builder uses ->get() by default that accepts only columns.
However, if your builder replaces functions like find(), $id is needed and you will also have to replace the getQueryCacheCallback() like so:
class MyCustomBuilder { public function getQueryCacheCallback(string $method = 'get', $columns = ['*'], $id = null) { return function () use ($method, $columns, $id) { $this->avoidCache = true; // the function for find() caching // accepts different params if ($method === 'find') { return $this->find($id, $columns); } return $this->{$method}($columns); }; } public function find($id, $columns = ['*']) { // implementing the same logic if (! $this->shouldAvoidCache()) { return $this->getFromQueryCache('find', $columns, $id); } return parent::find($id, $columns); } }
miradnan/laravel-model-caching 适用场景与选型建议
miradnan/laravel-model-caching 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 18.43k 次下载、GitHub Stars 达 8, 最近一次更新时间为 2020 年 04 月 14 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「sql」 「query」 「caching」 「laravel」 「eloquent」 「remember」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 miradnan/laravel-model-caching 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 miradnan/laravel-model-caching 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 miradnan/laravel-model-caching 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Query caching for Laravel 5
Query filtering in your frontend
Anax Database Active Record module for model classes.
Simple PHP caching system that uses a tmp folder in a Linux environment.
Provides support for PSR-6 compatible cache for Yii1 application
Database/ORM-agnostic query construction helper
统计信息
- 总下载量: 18.43k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 8
- 点击次数: 26
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2020-04-14