How to Create Own Cache driver and Learn Cache drivers from Laravel

How to Create Own Cache driver and Learn Cache drivers from Laravel

Hi guys,

Cache allows you to use your program more efficiently and reduces server demand. In this article, we look at How to Create Own Cache driver and Learn Cache drivers from Laravel.

Laravel provides an expressive, unified API for various caching backends. We stored all Cache information in the config/cache.php file of your project. They configure Laravel to use a file cache driver to keep the serialized cached objects in the filesystem.

Driver Prerequisites:-

Database:

You are going with a database cache driver. You will need to create a table that contains cache items.

Schema::create('cache', function ($table) {
    $table->string('key')->unique();
    $table->text('value');
    $table->integer('expiration');
});

Run the artisan command php artisan cache:table. It will generate a migration with the proper schema.

Memcached:

For Memcached driver requires a Memcached PECL package. You may list all the Memcached servers in the config/cache.php file.

'memcached' => [
    [
        'host' => '127.0.0.1',
        'port' => 11211,
        'weight' => 100
    ],
],

Cache Usage:-

Obtaining A Cache Instance:

The Illuminate\Contracts\Cache\Factory and Illuminate\Contracts\Cache\Repository contracts provide cache services in laravel. The factory gives all cached driver’s information defined in your application. It implements a repository default cache driver for your application.

<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\Cache;

class UserController extends Controller
{
    /**
     * Show a list of all users of the application.
     *
     * @return Response
     */
    public function index()
    {
        $value = Cache::get('key');

        //
    }
}

You may access various cache values stored in a different driver. You can access them with the store method.

$value = Cache::store('file')->get('foo');

Cache::store('redis')->put('bar', 'baz', 600); // 10 Minutes

Retrieving Items From The Cache:

The get method is to fetch data from the cached data. If a value does not exist, it will return null. You can also set a default value if the value does not exist.

$value = Cache::get('key');

$value = Cache::get('key', 'default');

You may pass a Closure as the default value. Giving a Closure allows you to defer the retrieval of default values from a database.

$value = Cache::get('key', function () {
    return DB::table(...)->get();
});

We use the has() method for checking whether a value exists or not. If the value does not exist, it will return to false.

if (Cache::has('key')) {
    //
}

The increment and decrement methods are used for adjusting integer values in the cached value. You can also pass the second parameter as a number, which increments or decrement values accordingly.

Cache::increment('key');
Cache::increment('key', $amount);
Cache::decrement('key');
Cache::decrement('key', $amount);

If you want to get data from a cache, but it does not exist then it retrieves them from the database and adds them into cached values using the Cache::remember method.

$value = Cache::remember('users', $seconds, function () {
    return DB::table('users')->get();
});

The rememberForever method retrieves an item from the cache or stores it forever:

$value = Cache::rememberForever('users', function () {
    return DB::table('users')->get();
});

You need to retrieve a value from the cache values and delete the item using the pull method.

$value = Cache::pull('key');

Storing items in the Cache:

You can store a value in the cached data using the put method. The third parameter is optional (it does not exist, it will keep the cached value forever).

Cache::put('key', 'value', $seconds);

Cache::put('key', 'value');

The add method applies to add value to cached data. If an item does not exist, it returns a boolean value. We add an item to the cached values. Otherwise, the method will return false. The forever method may store a value in the cached driver permanently.

Cache::add('key', 'value', $seconds);

Cache::forever('key', 'value');

Removing items from the Cache:

You may remove items from the cached values using the forget method and also clear the entire cached values. You can remove items by providing zero or negative TTL.

Cache::forget('key');

Cache::put('key', 'value', 0);

Cache::put('key', 'value', -5);

Cache::flush();

The Cache Helper:

The cache function applies to store and retrieve data via cached data. When the cache function passes a string argument, it will return the value of the key.

$value = cache('key');

To store values in the cached data. You need to pass an array of key-value pairs and expiration time to this function.

cache(['key' => 'value'], $seconds);

cache(['key' => 'value'], now()->addMinutes(10));

Cache Tags:-

Storing Tagged Cache Items:

Cache tags allow you to tag related items in the cached data and then flush all cached values assigned to a cache tag. You can access a tagged cache by passing in an array of cache tags.

Cache::tags(['people', 'artists'])->put('John', $john, $seconds);

Cache::tags(['people', 'authors'])->put('Anne', $anne, $seconds);

Accessing Tagged Cache Items:

To get a tagged cache item, pass the same ordered list of tags to the tags method and call the get method with a key you want to retrieve.

$john = Cache::tags(['people', 'artists'])->get('John');

$anne = Cache::tags(['people', 'authors'])->get('Anne');

Removing Tagged Cache Items:

You want to flush all values assigned to a tag or list of tag-to-tags methods.

Cache::tags(['people', 'authors'])->flush();
Cache::tags('authors')->flush();

Atomic Locks:-

Your application must use Memcached, dynamodb, Redis, database, or array for cached data.

Database Prerequisites:

If you are using a database cache driver, you need to set up a table to contain the cache locks.

Schema::create('cache_locks', function ($table) {
    $table->string('key')->primary();
    $table->string('owner');
    $table->integer('expiration');
});

Managing Locks:

Atomic locks allow you to manipulate distributed locks without worrying about race conditions. You can create and manage locks using the Cache::lock method. The get method accepts a closure. After they execute its Closure, laravel will automatically release the lock.

use Illuminate\Support\Facades\Cache;

$lock = Cache::lock('foo', 10);

if ($lock->get()) {
    // Lock acquired for 10 seconds...

    $lock->release();
}

Cache::lock('foo')->get(function () {
    // Lock acquired indefinitely and automatically released...
});

The lock is not available at the moment of request. You may instruct the application for a specific number of seconds. If it does not gain the lock to process within a specified time limit, it throws an exception of LockTimeoutException.

use Illuminate\Contracts\Cache\LockTimeoutException;

$lock = Cache::lock('foo', 10);

try {
    $lock->block(5);

    // Lock acquired after waiting maximum of 5 seconds...
} catch (LockTimeoutException $e) {
    // Unable to acquire lock...
} finally {
    optional($lock)->release();
}

Cache::lock('foo', 10)->block(5, function () {
    // Lock acquired after waiting maximum of 5 seconds...
});

Managing Locks Across Processes:

You want to acquire a lock in one process and release it in another process. In that case, pass the lock’s scoped “owner token” to the queued job so that the job can re-instantiate the locking process using the token. You want to force-release a lock without respecting its current owner. You may use the forceRelease method.

// Within Controller...
$podcast = Podcast::find($id);

$lock = Cache::lock('foo', 120);

if ($result = $lock->get()) {
    ProcessPodcast::dispatch($podcast, $lock->owner());
}

// Within ProcessPodcast Job...
Cache::restoreLock('foo', $this->owner)->release();


Cache::lock('foo')->forceRelease();

How to Create Own Cache Drivers?:-

Writing the driver:

To make our custom cache driver, we should implement the Illuminate\Contracts\Cache\Store contract.

<?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 should implement all the above methods. Once our implementation is complete, we can finish our custom driver’s registration.

Cache::extend('mongo', function ($app) {
    return Cache::repository(new MongoStore);
});

Registering the driver:

We use the extend method for registering custom cache drivers in laravel. The Cache::extend should be placed in the boot method in AppServiceProvider Provider.

<?php

namespace App\Providers;

use App\Extensions\MongoStore;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\ServiceProvider;

class CacheServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Cache::extend('mongo', function ($app) {
            return Cache::repository(new MongoStore);
        });
    }
}

The first argument is the name of the driver to extend the method. The second argument is a Closure that should return an Illuminate\Cache\Repository instance. We will pass the Closure an $app instance, an instance of the service container. After registering your extension, update the cache.php file’s driver option with the extension name.

Events:-

To execute code on every cache operation, you may listen for the events fired by the Cache. Typically, place these event listeners within your EventServiceProvider

/**
 * The event listener mappings for the application.
 *
 * @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',
    ],
];

I hope that this post (How to Create Own Cache Driver and Learn Cache Drivers from Laravel) has helped you understand access to the cache items from the store, assign tags to cache values, and create your cache driver. I used this site to write this post. Please leave a remark if you have any queries, and I will answer as quickly as possible.

Thank you for reading this article. Please share this article with your friend circle. That’s it for the day. Stay Connected!
Cheers

Loading

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top