Skip to content

Instantly share code, notes, and snippets.

@ttomdewit
Created January 5, 2017 09:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ttomdewit/3cc6512c27950d643155e9cc83425da1 to your computer and use it in GitHub Desktop.
Save ttomdewit/3cc6512c27950d643155e9cc83425da1 to your computer and use it in GitHub Desktop.
Trait for busting cache based on Eloquent events
<?php
namespace App\Traits;
use Illuminate\Support\Facades\Cache;
trait CacheBuster
{
public static function bootCacheBuster()
{
foreach (static::getCacheEvents() as $event) {
static::$event(function ($model) {
$keys = static::getCacheKeys($model);
foreach ($keys as $key) {
Cache::forget($key);
}
});
}
}
protected static function getCacheKeys($model)
{
$keys = static::cacheKeys();
$cacheKeys = [];
foreach ($keys as $key) {
$elements = explode('.', $key);
if (count($elements) > 1) {
$id = $elements[1];
if (! is_null($model->$id)) {
$elements[1] = str_replace($id, $model->$id, $elements[1]);
}
}
$cacheKeys[] = implode('.', $elements);
}
return $cacheKeys;
}
protected static function getCacheEvents()
{
if (isset(static::$cacheEvents)) {
return static::$cacheEvents;
}
return [
'created',
'updated',
'deleted',
];
}
}
@ttomdewit
Copy link
Author

On any given model you add the trait to your use statements.

<?php

namespace App\Models;

use App\Traits\CacheBuster;
use Illuminate\Database\Eloquent\Model;

And within your class declaration you add the following protected method:

class SomeModel extends Model
{

    use CacheBuster;
...

    /**
     * The keys that will help with cache flushing.
     *
     * @return array
     */
    protected static function cacheKeys() {
        return [
            'key',
            'key.id.key',
        ];
    }

...
}

Let's say you're caching results for 24 hours from an Eloquent call.

return Cache::remember('key', 60 * 24, function () {
    return SomeModel::all();
});

When using CacheBuster, the Cache key key will be flushed, meaning your latest change to any given SomeModel instance will be reflected in your next query.

Please note that this still needs some work, because I'm not always seeing changes directly.

@joshbrw
Copy link

joshbrw commented Jan 5, 2017

I normally use cache decoration on top of my repositories bound into the dependency container.

See a rough example at https://gist.github.com/joshbrw/6ddf41715cc3833eb64efb94543468a1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment