|
8 | 8 | use Illuminate\Database\Eloquent\Relations\MorphOne; |
9 | 9 | use Illuminate\Support\Facades\Cache; |
10 | 10 |
|
11 | | -/** |
12 | | - * Trait HasSettingsTable |
13 | | - * @package Glorand\Model\Settings\Traits |
14 | | - * @property ModelSettings $modelSettings |
15 | | - * @property array $settings |
16 | | - * @method morphOne($model, $name) |
17 | | - */ |
18 | 11 | trait HasSettingsTable |
19 | 12 | { |
20 | 13 | use HasSettings; |
21 | 14 |
|
| 15 | + protected $settingsRuntimeCache = null; |
| 16 | + protected $settingsManagerInstance = null; |
| 17 | + protected static $configCache = []; |
| 18 | + |
22 | 19 | /** |
23 | | - * @return \Glorand\Model\Settings\Contracts\SettingsManagerContract |
| 20 | + * Returns a settings manager instance for the model, creating one if necessary. |
| 21 | + * @return SettingsManagerContract |
24 | 22 | * @throws \Glorand\Model\Settings\Exceptions\ModelSettingsException |
25 | 23 | */ |
26 | 24 | public function settings(): SettingsManagerContract |
27 | 25 | { |
28 | | - return new TableSettingsManager($this); |
| 26 | + if ($this->settingsManagerInstance === null) { |
| 27 | + $this->settingsManagerInstance = new TableSettingsManager($this); |
| 28 | + } |
| 29 | + |
| 30 | + return $this->settingsManagerInstance; |
29 | 31 | } |
30 | 32 |
|
31 | 33 | /** |
| 34 | + * Retrieves the settings value for the model, optionally using a cache. |
32 | 35 | * @return array |
33 | 36 | */ |
34 | 37 | public function getSettingsValue(): array |
35 | 38 | { |
36 | | - if (config('model_settings.settings_table_use_cache')) { |
37 | | - return Cache::rememberForever($this->getSettingsCacheKey(), function () { |
38 | | - return $this->__getSettingsValue(); |
39 | | - }); |
| 39 | + // Runtime cache = ZERO Redis calls after first access |
| 40 | + if ($this->settingsRuntimeCache !== null) { |
| 41 | + return $this->settingsRuntimeCache; |
| 42 | + } |
| 43 | + |
| 44 | + // Cache config lookup once per class (not per instance) |
| 45 | + if (!isset(static::$configCache['use_cache'])) { |
| 46 | + static::$configCache['use_cache'] = config('model_settings.settings_table_use_cache'); |
| 47 | + } |
| 48 | + |
| 49 | + if (static::$configCache['use_cache']) { |
| 50 | + // Only 1 Redis call per request |
| 51 | + $this->settingsRuntimeCache = Cache::rememberForever( |
| 52 | + $this->getSettingsCacheKey(), |
| 53 | + fn() => $this->__getSettingsValue() |
| 54 | + ); |
| 55 | + } else { |
| 56 | + $this->settingsRuntimeCache = $this->__getSettingsValue(); |
40 | 57 | } |
41 | 58 |
|
42 | | - return $this->__getSettingsValue(); |
| 59 | + return $this->settingsRuntimeCache; |
43 | 60 | } |
44 | 61 |
|
| 62 | + /** |
| 63 | + * Retrieves the settings value for the model. |
| 64 | + * @return array |
| 65 | + */ |
45 | 66 | private function __getSettingsValue(): array |
46 | 67 | { |
47 | | - if ($modelSettings = $this->modelSettings()->first()) { |
48 | | - return $modelSettings->settings; |
| 68 | + // Eager loading support (prevents N+1) |
| 69 | + if ($this->relationLoaded('modelSettings')) { |
| 70 | + $modelSettings = $this->getRelation('modelSettings'); |
| 71 | + return $modelSettings ? $modelSettings->settings : []; |
49 | 72 | } |
50 | 73 |
|
51 | | - return []; |
| 74 | + $modelSettings = $this->modelSettings() |
| 75 | + ->select('settings', 'model_id', 'model_type') |
| 76 | + ->first(); |
| 77 | + |
| 78 | + return $modelSettings ? $modelSettings->settings : []; |
52 | 79 | } |
53 | 80 |
|
54 | 81 | /** |
55 | | - * @return \Illuminate\Database\Eloquent\Relations\MorphOne |
| 82 | + * Define an inverse one-to-one or many relationship. |
| 83 | + * @return MorphOne |
56 | 84 | */ |
57 | 85 | public function modelSettings(): MorphOne |
58 | 86 | { |
59 | 87 | return $this->morphOne(ModelSettings::class, 'model'); |
60 | 88 | } |
61 | 89 |
|
| 90 | + /** |
| 91 | + * Retrieves the cache key for settings associated with the model. |
| 92 | + * |
| 93 | + * This method ensures that a consistent cache key is generated for |
| 94 | + * the model's settings by utilizing a shared static configuration |
| 95 | + * for the cache prefix and combining it with the table name and |
| 96 | + * primary key of the current model instance. |
| 97 | + * |
| 98 | + * @return string The generated cache key for the model's settings. |
| 99 | + */ |
62 | 100 | public function getSettingsCacheKey(): string |
63 | 101 | { |
64 | | - return config('model_settings.settings_table_cache_prefix') . $this->getTable() . '::' . $this->getKey(); |
| 102 | + // Static config cache shared across all instances |
| 103 | + if (!isset(static::$configCache['cache_prefix'])) { |
| 104 | + static::$configCache['cache_prefix'] = config('model_settings.settings_table_cache_prefix'); |
| 105 | + } |
| 106 | + |
| 107 | + return static::$configCache['cache_prefix'] . $this->getTable() . '::' . $this->getKey(); |
| 108 | + } |
| 109 | + |
| 110 | + /** |
| 111 | + * Clears the runtime cache and optionally the cache for the model's settings.' |
| 112 | + * @return void |
| 113 | + */ |
| 114 | + public function clearSettingsCache(): void |
| 115 | + { |
| 116 | + $this->settingsRuntimeCache = null; |
| 117 | + |
| 118 | + if (static::$configCache['use_cache'] ?? config('model_settings.settings_table_use_cache')) { |
| 119 | + Cache::forget($this->getSettingsCacheKey()); |
| 120 | + } |
65 | 121 | } |
66 | 122 |
|
| 123 | + /** |
| 124 | + * Retrieves the name of the database table associated with the model. |
| 125 | + * @return string |
| 126 | + */ |
67 | 127 | abstract public function getTable(); |
68 | 128 | } |
0 commit comments