caching system
Laravel provides rich and unified caching for various backends API, its configuration information is located in the
config/cache.php file. In this file you can specify which cache driver the application uses by default. Laravel supports currently popular backend caches, such as Memcached
and Redis. The cache configuration file also contains various other options, which are documented in the file, so be sure to read these options. By default, Laravel is configured to use the
cache driver, which stores serialized cache objects in the file system. For larger applications, it is recommended that you use a more powerful driver such as Memcached or Redis. You can even configure multiple cache configurations for the same driver.
Database
When using the database
cache driver, you need to configure a table to store cache data. The following is an example of the Schema
declaration to build the cache data table structure:
Schema::create('cache', function ($table) { $table->string('key')->unique(); $table->text('value'); $table->integer('expiration'); });
{tip} You can also use the Artisan command
php artisan cache:table
to generate it Suitable migration.
Memcached
Using the Memcached driver requires installing the Memcached PECL extension package. You can list all Memcached servers in the config/cache.php
configuration file:
'memcached' => [ [ 'host' => '127.0.0.1', 'port' => 11211, 'weight' => 100 ], ],
You can set the host
option to the UNIX socket path. If you configure it this way, the port
option should be set to 0
:
'memcached' => [ [ 'host' => '/var/run/memcached/memcached.sock', 'port' => 0, 'weight' => 100 ], ],
Redis
When using Laravel's Redis Before caching, you need to install the predis/predis
extension package (~1.0) through Composer or use PECL to install the PhpRedis PHP extension.
To learn more about Redis configuration, please refer to the Laravel Redis documentation.
Use of cache
Get cache instance
Illuminate\Contracts\Cache\Factory
and Illuminate\Contracts\Cache\Repository
contracts provide the access mechanism for Laravel cache services. Factory
The contract defines the mechanism for your application to access all cache drivers. Repository
The contract is usually implemented by the default cache driver specified in your cache
configuration file.
However, you can also use the Cache
Facade, which we will introduce in subsequent documents. Cache
Facade provides a convenient and concise method for the underlying implementation of Laravel cache contract:
<?php namespace App\Http\Controllers; use Illuminate\Support\Facades\Cache; class UserController extends Controller{ /** * 展示应用的所有用户列表。 * * @return Response */ public function index() { $value = Cache::get('key'); // } }
Access multiple cache storage
UseCache
Facade, you can access various cache stores through the store
method. The key passed into the store
method should correspond to one of the stores listed in the stores
configuration array in the cache
configuration information file:
$value = Cache::store('file')->get('foo'); Cache::store('redis')->put('bar', 'baz', 600); // 10 分钟
Get data from the cache
Cache
The get
method of Facade is the method used to get data from the cache. If the data does not exist in the cache, the method will return null
. As you might imagine, you can also pass a second parameter to the get
method to specify the default value you want returned if the data being looked up does not exist:
$value = Cache::get('key'); $value = Cache::get('key', 'default');
You can even Closure
can be passed as the default value. If the specified data does not exist in the cache, the result of Closure
will be returned. Methods passing a closure allow you to get the default value from a database or other external service:
$value = Cache::get('key', function () { return DB::table(...)->get(); });
Check if the cache item exists
has
method Can be used to determine whether cache items exist. If it is null
or false
, this method will return false
:
if (Cache::has('key')) { // }
Incrementing and decrementing values## The
#increment and
decrement methods can be used to adjust the value of an integer item in the cache. Both methods can pass in a second optional parameter, which is used to specify the amount to be incremented or decremented:
Cache::increment('key'); Cache::increment('key', $amount); Cache::decrement('key'); Cache::decrement('key', $amount);Getting and storingSometimes You may want to get a data from the cache, and when the requested cache item does not exist, the program can store a default value for you. For example, you may want to get all users from the cache. When these users do not exist in the cache, the program will fetch these users from the database and put them in the cache. You can use the
Cache::remember method to achieve this:
$value = Cache::remember('users', $seconds, function () { return DB::table('users')->get(); });If the data you want does not exist in the cache, pass it to the
remember method
The closure will be executed and its result returned and placed in the cache.
rememberForever method:
$value = Cache::rememberForever('users', function () { return DB::table('users')->get(); });Get and deleteif You need to get the data from the cache before deleting it. You can use the
pull method. Like the
get method, if the cache does not exist,
null is returned:
$value = Cache::pull('key');Storing data in the cacheYou can use the
put method of the
Cache Facade to store data in the cache:
Cache::put('key', 'value', $seconds);If the cache expires If the time is not passed to the
put method, the cache will be valid forever:
Cache::put('key', 'value');In addition to passing the expiration time in seconds as an integer, you can also pass a
DateTime instance To indicate the expiration time of the data:
Cache::put('key', 'value', now()->addMinutes(10));Only store data that does not exist
add The method will only store data that does not exist in the cache. If the storage is successful,
true will be returned, otherwise
false will be returned:
Cache::add('key', 'value', $seconds);
Data Permanent Storage
forever
method can be used to persistently store data into the cache. Because these data do not expire, they must be manually removed from the cache via the forget
method:
Cache::forever('key', 'value');
{tip} If you use the Memcached driver, when the cached data reaches the storage For a limited time, data in "persistent storage" may be deleted.
Delete the data in the cache
You can use the forget
method from Delete this data from the cache:
Cache::forget('key');
You can also delete this data by providing a zero or negative TTL value:
Cache::put('key', 'value', 0); Cache::put('key', 'value', -5);
You can use the flush
method to clear all caches :
Cache::flush();
{note} The method of clearing the cache does not consider the cache prefix and will delete all content in the cache. So please consider carefully when clearing cache shared with other applications.
Atomic Lock
{note} To use this feature, your application must Use the
memcached
,dynamodb
orredis
cache driver as the default cache driver for your application. Additionally, all servers must communicate with the same central cache server.
Atomic locks allow operations on distributed locks without worrying about race conditions. For example, Laravel Forge uses atomic locks to ensure that only one remote task is executed on a server at a time. You can create and manage locks using the Cache::lock
method: The
use Illuminate\Support\Facades\Cache; $lock = Cache::lock('foo', 10); if ($lock->get()) { //获取锁定10秒... $lock->release(); }
get
method can also receive a closure. After the closure is executed, Laravel will automatically release the lock:
Cache::lock('foo')->get(function () { // 获取无限期锁并自动释放... });
If the lock is not available at the time of your request, you can control Laravel to wait for a specified number of seconds. If the lock cannot be acquired within the specified time limit, Illuminate\Contracts\Cache\LockTimeoutException
will be thrown:
use Illuminate\Contracts\Cache\LockTimeoutException; $lock = Cache::lock('foo', 10);try { $lock->block(5); // 等待最多5秒后获取的锁... } catch (LockTimeoutException $e) { // 无法获取锁... } finally { optional($lock)->release(); } Cache::lock('foo', 10)->block(5, function () { // 等待最多5秒后获取的锁... });
Manage cross-process locks
Sometimes, you want to acquire a lock in one process and release it in another process. For example, you could acquire a lock during a web request and want to release the lock when the queue job triggered by that request ends. In this case, you should pass the lock's scope "owner token" to the queue job so that the job can re-instantiate the lock with the given token:
// 控制器里面... $podcast = Podcast::find($id); if ($lock = Cache::lock('foo', 120)->get()) { ProcessPodcast::dispatch($podcast, $lock->owner()); } // ProcessPodcast Job 里面... Cache::restoreLock('foo', $this->owner)->release();
If you want to do this without respecting the current lock To release the lock without the owner, you can use the forceRelease
method:
Cache::lock('foo')->forceRelease();
Cache auxiliary function
In addition to using the Cache
Facade or Cache contract, you can also use the global auxiliary function cache
to obtain and save cache data. When the cache
function only receives a string parameter, it will return the value corresponding to the given key:
$value = cache('key');
If you provide the function with a set of key-value pairs and expiration time , it will cache the data for the specified time:
cache(['key' => 'value'], $seconds); cache(['key' => 'value'], now()->addMinutes(10));
When the cache
function is called without any parameters, it returns a Illuminate\Contracts\Cache\ An instance of the Factory
implementation that allows you to call other cache methods:
cache()->remember('users', $seconds, function () { return DB::table('users')->get(); });
{tip} If you use the global helper function
cache
in your tests, you can useThe Cache::shouldReceive
method is like testing the Facade.
Cache tag
{note} Cache tag is not supported using
file
anddatabase
cache drivers. In addition, a cache driver likememcached
performs best when the cache using multiple cache tags is set to "persistent", which automatically clears old records.
Write tagged cache data
Cache tags allow you to tag cache related data. So that these cached values can be cleared later. You can access the cache of tags by passing in an ordered array of tag names. For example, we can set the cache using the put
method while using the tag.
Cache::tags(['people', 'artists'])->put('John', $john, $seconds); Cache::tags(['people', 'authors'])->put('Anne', $anne, $seconds);
Access marked cache data
To obtain a marked cache data, please change the same Pass an ordered array of tags to the tags
method, then call the get
method to get the key you want to retrieve:
$john = Cache::tags(['people', 'artists'])->get('John'); $anne = Cache::tags(['people', 'authors'])->get('Anne');
Remove marked cache data
You can clear all cached data with a single mark or a group of marks. For example, the following statement would be cached as people
, authors
, or both. Therefore, both Anne
and John
will be deleted from the cache:
Cache::tags(['people', 'authors'])->flush();
In contrast, the following statement will only delete the cache marked authors
, so Anne
will be deleted, but John
will not:
Cache::tags('authors')->flush();
increase Custom cache driver
Writing Driver
To create a custom cache driver, you first need to implement the Illuminate\Contracts\Cache\Store
contract. Therefore, MongoDB's cache implementation will look like this:
<?php namespace App\Extensions; use Illuminate\Contracts\Cache\Store; class MongoStore implements Store{ public function get($key) {} public function many(array $keys); public function put($key, $value, $seconds) {} public function putMany(array $values, $seconds); public function increment($key, $value = 1) {} public function decrement($key, $value = 1) {} public function forever($key, $value) {} public function forget($key) {} public function flush() {} public function getPrefix() {} }
We only need the MongoDB connection to implement these methods. For examples of how to implement these methods, see Illuminate\Cache\MemcachedStore
in the framework source code. Once the contract is completed, you can complete the registration of the custom driver as follows.
Cache::extend('mongo', function ($app) { return Cache::repository(new MongoStore); });
{tip} If you don't know where to put the cache driver code, you can create an
Extensions
namespace in theapp
directory. However, Laravel does not dictate the structure of your application and you are free to organize your application however you like.
Register driver
To use Laravel to register a custom cache driver, you must Cache
Use the extend
method on the Facade. The call to Cache::extend
can be done in the boot
method of App\Providers\AppServiceProvider
that comes with the new Laravel application, or you can also You can create your own service provider to store extensions, but don't forget to register the service provider in the provider array of config/app.php
:
<?php namespace App\Providers;use App\Extensions\MongoStore; use Illuminate\Support\Facades\Cache; use Illuminate\Support\ServiceProvider; class CacheServiceProvider extends ServiceProvider{ /** * 执行服务的注册后引导。 * * @return void */ public function boot() { Cache::extend('mongo', function ($app) { return Cache::repository(new MongoStore); }); } /** * 在容器中注册绑定。 * * @return void */ public function register() { // } }
is passed to extend
The first parameter of the method is the name of the driver. This will correspond to the driver
option of the config/cache.php
configuration file. The second parameter is a closure that should return an instance of Illuminate\Cache\Repository
. The closure will be passed an $app
instance of the service container.
Once your extension is registered, you need to update the driver
option in the config/cache.php
configuration file to your extension name.
Events
To execute code on every cache operation, you can listen to events triggered by the cache. Typically, you should place these event listeners in EventServiceProvider
:
/** * 应用的事件监听器映射 * * @var array */ protected $listen = [ 'Illuminate\Cache\Events\CacheHit' => [ 'App\Listeners\LogCacheHit', ], 'Illuminate\Cache\Events\CacheMissed' => [ 'App\Listeners\LogCacheMissed', ], 'Illuminate\Cache\Events\KeyForgotten' => [ 'App\Listeners\LogKeyForgotten', ], 'Illuminate\Cache\Events\KeyWritten' => [ 'App\Listeners\LogKeyWritten', ], ];