88use Illuminate \Database \Eloquent \Relations \MorphOne ;
99use Illuminate \Support \Facades \Cache ;
1010
11+ /**
12+ * Trait HasSettingsTable
13+ * @package Glorand\Model\Settings\Traits
14+ *
15+ * @property ModelSettings $modelSettings
16+ * @property array $settings
17+ * @method morphOne(string $related, string $name, string $type = null, string $id = null, string $localKey = null)
18+ */
1119trait HasSettingsTable
1220{
1321 use HasSettings;
1422
15- protected $ settingsRuntimeCache = null ;
16- protected $ settingsManagerInstance = null ;
17- protected static $ configCache = [];
23+ /** @var SettingsManagerContract|null */
24+ private ?SettingsManagerContract $ _settingsManager = null ;
1825
19- /**
20- * Returns a settings manager instance for the model, creating one if necessary.
21- * @return SettingsManagerContract
22- * @throws \Glorand\Model\Settings\Exceptions\ModelSettingsException
26+ /** @var array|null In-memory copy */
27+ private ?array $ _settingsCache = null ;
28+
29+ /* -----------------------------------------------------------------
30+ | Boot – register model event listeners
31+ | -----------------------------------------------------------------
2332 */
24- public function settings (): SettingsManagerContract
33+ public static function bootHasSettingsTable (): void
2534 {
26- if ($ this ->settingsManagerInstance === null ) {
27- $ this ->settingsManagerInstance = new TableSettingsManager ($ this );
28- }
35+ // When the polymorphic row changes, flush our caches
36+ static ::saved (function ($ model ) {
37+ $ model ->flushSettingsCache ();
38+ Cache::forget ($ model ->getSettingsCacheKey ());
39+ });
40+
41+ static ::deleted (function ($ model ) {
42+ $ model ->flushSettingsCache ();
43+ Cache::forget ($ model ->getSettingsCacheKey ());
44+ });
45+ }
2946
30- return $ this ->settingsManagerInstance ;
47+ /* -----------------------------------------------------------------
48+ | Settings Manager
49+ | -----------------------------------------------------------------
50+ */
51+ public function settings (): SettingsManagerContract
52+ {
53+ return $ this ->_settingsManager ??= new TableSettingsManager ($ this );
3154 }
3255
33- /**
34- * Retrieves the settings value for the model, optionally using a cache.
35- * @return array
56+ /* -----------------------------------------------------------------
57+ | Settings Value (lazy + in-memory)
58+ | -----------------------------------------------------------------
3659 */
3760 public function getSettingsValue (): array
3861 {
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 ' );
62+ if ($ this ->_settingsCache !== null ) {
63+ return $ this ->_settingsCache ;
4764 }
4865
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 ();
66+ if (! config ('model_settings.settings_table_use_cache ' )) {
67+ return $ this ->_settingsCache = $ this ->loadSettingsFromDatabase ();
5768 }
5869
59- return $ this ->settingsRuntimeCache ;
70+ return $ this ->_settingsCache = Cache::rememberForever (
71+ $ this ->getSettingsCacheKey (),
72+ fn () => $ this ->loadSettingsFromDatabase ()
73+ );
6074 }
6175
6276 /**
63- * Retrieves the settings value for the model.
64- * @return array
77+ * Reload settings and refresh all caches.
6578 */
66- private function __getSettingsValue (): array
79+ public function refreshSettings (): array
6780 {
68- // Eager loading support (prevents N+1)
69- if ($ this ->relationLoaded ('modelSettings ' )) {
70- $ modelSettings = $ this ->getRelation ('modelSettings ' );
71- return $ modelSettings ? $ modelSettings ->settings : [];
72- }
73-
74- $ modelSettings = $ this ->modelSettings ()
75- ->select ('settings ' , 'model_id ' , 'model_type ' )
76- ->first ();
81+ $ this ->flushSettingsCache ();
82+ Cache::forget ($ this ->getSettingsCacheKey ());
7783
78- return $ modelSettings ? $ modelSettings -> settings : [] ;
84+ return $ this -> getSettingsValue () ;
7985 }
8086
8187 /**
82- * Define an inverse one-to-one or many relationship.
83- * @return MorphOne
88+ * Flush only the in-RAM copy.
8489 */
85- public function modelSettings (): MorphOne
90+ public function flushSettingsCache (): void
8691 {
87- return $ this ->morphOne (ModelSettings::class, ' model ' ) ;
92+ $ this ->_settingsCache = null ;
8893 }
8994
9095 /**
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.
96+ * Raw DB hit (no caching layer).
9997 */
100- public function getSettingsCacheKey (): string
98+ private function loadSettingsFromDatabase (): array
10199 {
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- }
100+ /** @var ModelSettings|null $row */
101+ $ row = $ this ->modelSettings ()->first (['settings ' ]);
106102
107- return static :: $ configCache [ ' cache_prefix ' ] . $ this -> getTable () . ' :: ' . $ this -> getKey () ;
103+ return $ row ?->settings ?? [] ;
108104 }
109105
110- /**
111- * Clears the runtime cache and optionally the cache for the model's settings.'
112- * @return void
106+ /* -----------------------------------------------------------------
107+ | Relations
108+ | -----------------------------------------------------------------
113109 */
114- public function clearSettingsCache (): void
110+ public function modelSettings (): MorphOne
115111 {
116- $ this ->settingsRuntimeCache = null ;
112+ return $ this ->morphOne (ModelSettings::class, 'model ' );
113+ }
117114
118- if (static ::$ configCache ['use_cache ' ] ?? config ('model_settings.settings_table_use_cache ' )) {
119- Cache::forget ($ this ->getSettingsCacheKey ());
120- }
115+
116+ /* -----------------------------------------------------------------
117+ | Helpers
118+ | -----------------------------------------------------------------
119+ */
120+ public function getSettingsCacheKey (): string
121+ {
122+ return config ('model_settings.settings_table_cache_prefix ' )
123+ . $ this ->getTable () . ':: ' . $ this ->getKey ();
121124 }
122125
123- /**
124- * Retrieves the name of the database table associated with the model.
125- * @return string
126+ /* -----------------------------------------------------------------
127+ | Abstract requirements
128+ | -----------------------------------------------------------------
126129 */
127130 abstract public function getTable ();
128- }
131+ }
0 commit comments