Skip to content

Commit 7ded669

Browse files
authored
Merge pull request #17 from efureev/cache-trait
feat: divide EntityCacheTrait
2 parents 0821254 + 81c8cbb commit 7ded669

File tree

4 files changed

+150
-43
lines changed

4 files changed

+150
-43
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Php\Support\Laravel\Traits\Models\Cachers;
6+
7+
interface CacherContract
8+
{
9+
public function prefixKey(string $key = null, string $prefix = null): string;
10+
11+
public function cacheForgetCollection(string $key = null): bool;
12+
13+
public function forgetByKey(string $key): bool;
14+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Php\Support\Laravel\Traits\Models\Cachers;
6+
7+
class DummyCacher implements CacherContract
8+
{
9+
public function __construct(private readonly string $model)
10+
{
11+
}
12+
13+
public function prefixKey(string $key = null, string $prefix = null): string
14+
{
15+
$prefix ??= class_basename($this->model);
16+
17+
return "app:models:$prefix:$key";
18+
}
19+
20+
public function cacheForgetCollection(string $key = null): bool
21+
{
22+
return true;
23+
}
24+
25+
public function forgetByKey(string $key): bool
26+
{
27+
return true;
28+
}
29+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Php\Support\Laravel\Traits\Models\Cachers;
6+
7+
use Illuminate\Contracts\Cache\Store;
8+
use Illuminate\Support\Facades\Config;
9+
10+
class RedisCacher implements CacherContract
11+
{
12+
/**
13+
* @param \Illuminate\Cache\RedisStore $store
14+
*/
15+
public function __construct(private readonly string $model, private readonly Store $store)
16+
{
17+
}
18+
19+
public function prefixKey(string $key = null, string $prefix = null): string
20+
{
21+
$prefix ??= class_basename($this->model);
22+
23+
return "app:models:$prefix:$key";
24+
}
25+
26+
public function cacheForgetCollection(string $key = null): bool
27+
{
28+
return $this->removeByTemplate($this->prefixKey($key ?? 'list:*'));
29+
}
30+
31+
private function removeByTemplate(string $template): bool
32+
{
33+
$client = $this->store->connection()->client();
34+
35+
if (Config::get('database.redis.client') === 'predis') {
36+
$key = $this->store->getPrefix() . $template;
37+
} else {
38+
$key = $client->_prefix($template);
39+
}
40+
41+
$lua = <<<LUA
42+
local keys = unpack(redis.call('keys', KEYS[1]))
43+
if not keys then
44+
return 0
45+
end
46+
47+
return redis.call('del', keys)
48+
LUA;
49+
50+
$result = $client->eval(
51+
$lua,
52+
1,
53+
$key
54+
);
55+
56+
return $result > 0;
57+
}
58+
59+
public function forgetByKey(string $key): bool
60+
{
61+
return $this->store->forget($this->prefixKey($key));
62+
}
63+
}

src/Traits/Models/HasModelEntityCache.php

Lines changed: 44 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,60 @@
44

55
namespace Php\Support\Laravel\Traits\Models;
66

7+
use Illuminate\Cache\RedisStore;
78
use Illuminate\Database\Eloquent\Model;
89
use Illuminate\Support\Facades\Cache;
910
use Illuminate\Support\Facades\Config;
11+
use Php\Support\Laravel\Traits\Models\Cachers\CacherContract;
12+
use Php\Support\Laravel\Traits\Models\Cachers\DummyCacher;
13+
use Php\Support\Laravel\Traits\Models\Cachers\RedisCacher;
1014

1115
/**
1216
* @mixin Model
1317
*/
1418
trait HasModelEntityCache
1519
{
20+
public static bool $cacheEnable = true;
21+
22+
public static function disableCache(): void
23+
{
24+
static::$cacheEnable = false;
25+
}
26+
1627
public static function bootHasModelEntityCache(): void
1728
{
1829
static::registerEventsForCache();
1930
}
2031

32+
protected static array $cacheStores = [];
33+
34+
protected static function resolveStoreDriver(): CacherContract
35+
{
36+
return static::$cacheStores[static::class] ??= static::resolveStoreDriverCls();
37+
}
38+
39+
protected static function getEntityCacheResolver(): ?CacherContract
40+
{
41+
$cacheResolverCls = Config::get('cache.resolver.class');
42+
if (class_exists($cacheResolverCls)) {
43+
return $cacheResolverCls(static::class, Cache::getStore());
44+
}
45+
46+
return null;
47+
}
48+
49+
protected static function resolveStoreDriverCls(): CacherContract
50+
{
51+
if ($cacheResolverCls = static::getEntityCacheResolver()) {
52+
return $cacheResolverCls;
53+
}
54+
55+
return $cacheResolver ?? match (Cache::getStore()::class) {
56+
RedisStore::class => new RedisCacher(static::class, Cache::getStore()),
57+
default => new DummyCacher(static::class),
58+
};
59+
}
60+
2161
protected static function registerEventsForCache(): void
2262
{
2363
static::saved($fn = static::cacheForgetFn());
@@ -51,42 +91,12 @@ public static function cacheForgetByKey(string $key): bool
5191
return true;
5292
}
5393

54-
return Cache::forget(static::cachePrefixKey($key));
94+
return static::resolveStoreDriver()->forgetByKey($key);
5595
}
5696

57-
protected static function cacheForgetCollection(string $key = 'list:*'): bool
97+
protected static function cacheForgetCollection(string $key = null): bool
5898
{
59-
return static::removeByTemplate(static::cachePrefixKey($key));
60-
}
61-
62-
private static function removeByTemplate(string $template)
63-
{
64-
/** @var \Illuminate\Cache\RedisStore $store */
65-
$store = Cache::getStore();
66-
$client = $store->connection()->client();
67-
68-
if (Config::get('database.redis.client') === 'predis') {
69-
$key = $store->getPrefix() . $template;
70-
} else {
71-
$key = $client->_prefix($template);
72-
}
73-
74-
$lua = <<<LUA
75-
local keys = unpack(redis.call('keys', KEYS[1]))
76-
if not keys then
77-
return 0
78-
end
79-
80-
return redis.call('del', keys)
81-
LUA;
82-
83-
$result = $client->eval(
84-
$lua,
85-
1,
86-
$key
87-
);
88-
89-
return $result > 0;
99+
return static::resolveStoreDriver()->cacheForgetCollection($key);
90100
}
91101

92102
protected static function cacheKeyName(): string
@@ -96,23 +106,14 @@ protected static function cacheKeyName(): string
96106

97107
protected static function cachePrefixKey(string $key = null, string $prefix = null): string
98108
{
99-
$prefix ??= class_basename(static::class);
100-
101-
return "app:models:$prefix:$key";
109+
return static::resolveStoreDriver()->prefixKey($key, $prefix);
102110
}
103111

104112
protected static function cacheTtl(): int
105113
{
106114
return 60 * 60;
107115
}
108116

109-
public static bool $cacheEnable = true;
110-
111-
public static function disableCache(): void
112-
{
113-
static::$cacheEnable = false;
114-
}
115-
116117
public static function remember(callable $fn, string $key): mixed
117118
{
118119
if (!static::$cacheEnable) {

0 commit comments

Comments
 (0)