Skip to content

Commit

Permalink
Merge pull request #19 from rennokki/feature/clear-cache-for-model
Browse files Browse the repository at this point in the history
[feature] Full cache purging for all resources
  • Loading branch information
rennokki authored Apr 19, 2020
2 parents 1895fc6 + 0941df3 commit 61e59fb
Show file tree
Hide file tree
Showing 11 changed files with 193 additions and 2 deletions.
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,37 @@ $alice = Kid::whereName('Alice')->cacheFor(60)->cacheTags(['kids'])->first();
$bob = Kid::whereName('Bob')->cacheFor(60)->cacheTags(['kids'])->first();
```

### Global Cache Invalidation

To invalidate all the cache for a specific model, use the `flushQueryCache` method without passing the tags.

The package automatically appends a list of tags, called **base tags** on each query coming from a model. It defaults to the full model class name.

In case you want to change the base tags, you can do so in your model.

```php
class Kid extends Model
{
use QueryCacheable;

/**
* Set the base cache tags that will be present
* on all queries.
*
* @return array
*/
protected function getCacheBaseTags(): array
{
return [
'custom_tag',
];
}
}

// Automatically works with `custom_tag`
Kid::flushQueryCache();
```

## 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.

Expand Down
19 changes: 19 additions & 0 deletions database/factories/BookFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php
/*
|--------------------------------------------------------------------------
| Model Factories
|--------------------------------------------------------------------------
|
| This directory should contain each of the model factory definitions for
| your application. Factories provide a convenient way to generate new
| model instances for testing / seeding your application's database.
|
*/

use Illuminate\Support\Str;

$factory->define(\Rennokki\QueryCache\Test\Models\Book::class, function () {
return [
'name' => 'Book'.Str::random(5),
];
});
42 changes: 41 additions & 1 deletion src/Traits/QueryCacheModule.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ trait QueryCacheModule
*/
protected $cacheTags = null;

/**
* The tags for the query cache that
* will be present on all queries.
*
* @var null|array
*/
protected $cacheBaseTags = null;

/**
* The cache driver to be used.
*
Expand Down Expand Up @@ -163,6 +171,10 @@ public function flushQueryCache(array $tags = []): bool
return false;
}

if (! $tags) {
$tags = $this->getCacheBaseTags();
}

foreach ($tags as $tag) {
self::flushQueryCacheWithTag($tag);
}
Expand Down Expand Up @@ -272,6 +284,20 @@ public function cacheDriver(string $cacheDriver)
return $this;
}

/**
* Set the base cache tags; the tags
* that will be present on all cached queries.
*
* @param array $tags
* @return \Rennokki\QueryCache\Query\Builder
*/
public function cacheBaseTags(array $tags = [])
{
$this->cacheBaseTags = $tags;

return $this;
}

/**
* Use a plain key instead of a hashed one in the cache driver.
*
Expand Down Expand Up @@ -302,7 +328,11 @@ public function getCacheDriver()
public function getCache()
{
$cache = $this->getCacheDriver();
$tags = $this->getCacheTags();

$tags = array_merge(
$this->getCacheTags() ?: [],
$this->getCacheBaseTags() ?: []
);

return $tags ? $cache->tags($tags) : $cache;
}
Expand Down Expand Up @@ -348,6 +378,16 @@ public function getCacheTags()
return $this->cacheTags;
}

/**
* Get the base cache tags attribute.
*
* @return array|null
*/
public function getCacheBaseTags()
{
return $this->cacheBaseTags;
}

/**
* Get the cache prefix attribute.
*
Expand Down
16 changes: 15 additions & 1 deletion src/Traits/QueryCacheable.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,20 @@ protected function newBaseQueryBuilder()
$builder->withPlainKey();
}

return $builder;
return $builder
->cacheBaseTags($this->getCacheBaseTags());
}

/**
* Set the base cache tags that will be present
* on all queries.
*
* @return array
*/
protected function getCacheBaseTags(): array
{
return [
(string) self::class,
];
}
}
16 changes: 16 additions & 0 deletions tests/MethodsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Rennokki\QueryCache\Test;

use Cache;
use Rennokki\QueryCache\Test\Models\Book;
use Rennokki\QueryCache\Test\Models\Kid;
use Rennokki\QueryCache\Test\Models\Post;

Expand Down Expand Up @@ -89,6 +90,21 @@ public function test_cache_flush_with_more_tags()
$this->assertNull($cache);
}

public function test_cache_flush_with_default_tags_attached()
{
$book = factory(Book::class)->create();
$storedBook = Book::cacheFor(now()->addHours(1))->cacheTags(['test'])->first();

$cache = Cache::tags(['test', Book::getCacheBaseTags()[0]])->get('leqc:sqlitegetselect * from "books" limit 1a:0:{}');
$this->assertNotNull($cache);

Book::flushQueryCache();

$cache = Cache::tags(['test', Book::getCacheBaseTags()[0]])->get('leqc:sqlitegetselect * from "books" limit 1a:0:{}');

$this->assertNull($cache);
}

public function test_hashed_key()
{
$kid = factory(Kid::class)->create();
Expand Down
17 changes: 17 additions & 0 deletions tests/Models/Book.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace Rennokki\QueryCache\Test\Models;

use Illuminate\Database\Eloquent\Model;
use Rennokki\QueryCache\Traits\QueryCacheable;

class Book extends Model
{
use QueryCacheable;

protected $cacheUsePlainKey = true;

protected $fillable = [
'name',
];
}
7 changes: 7 additions & 0 deletions tests/Models/Kid.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,11 @@ class Kid extends Model
protected $fillable = [
'name',
];

protected function getCacheBaseTags(): array
{
return [
//
];
}
}
7 changes: 7 additions & 0 deletions tests/Models/Post.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,11 @@ class Post extends Model
protected $fillable = [
'name',
];

protected function getCacheBaseTags(): array
{
return [
//
];
}
}
7 changes: 7 additions & 0 deletions tests/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,11 @@ class User extends Authenticatable
protected $hidden = [
'password', 'remember_token',
];

protected function getCacheBaseTags(): array
{
return [
//
];
}
}
1 change: 1 addition & 0 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public function getEnvironmentSetUp($app)
$app['config']->set('auth.providers.users.model', User::class);
$app['config']->set('auth.providers.posts.model', Post::class);
$app['config']->set('auth.providers.kids.model', Kid::class);
$app['config']->set('auth.providers.books.model', Book::class);
$app['config']->set('app.key', 'wslxrEFGWY6GfGhvN9L3wH3KSRJQQpBD');
}

Expand Down
32 changes: 32 additions & 0 deletions tests/database/migrations/2018_07_14_183253_books.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class Books extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('books', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('books');
}
}

0 comments on commit 61e59fb

Please sign in to comment.