Skip to content

Commit 70fce70

Browse files
committed
feat: add runtime flags for dynamic behavior control
- Add HasFlags trait with enable/disable/toggle flag methods - Implement flag checking methods (hasFlag, hasAnyFlag, hasAllFlags) - Add batch operations for multiple flags (enableFlags, disableFlags) - Include clearFlags method to reset all flags This allows conditional behavior control during execution without external configuration, perfect for testing, feature toggles, and environment-specific behavior.
1 parent f4dfb36 commit 70fce70

5 files changed

Lines changed: 488 additions & 3 deletions

File tree

README.md

Lines changed: 113 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,12 @@ Organize cache by classes or contexts
4545
🧠 **LRU Cache**
4646
Automatic memory management with size limits
4747

48-
🎯 **Simple API**
49-
Intuitive facade and helper functions
50-
5148
📊 **Cache Analytics**
5249
Built-in statistics and monitoring
5350

51+
🏃 **Runtime Flags**
52+
Dynamic behavior control during execution
53+
5454
</td>
5555
</tr>
5656
</table>
@@ -144,6 +144,116 @@ memoize()->for('App\\Model\\User')->forget('123');
144144
memoize()->flush();
145145
```
146146

147+
#### 🏃 **Runtime Flags**
148+
149+
Control memoization behavior dynamically during execution with runtime flags. These flags exist only in memory and reset between requests/processes.
150+
151+
**How do runtime flags work?**
152+
- Flags are stored in memory during the current execution
153+
- They allow conditional behavior without external configuration
154+
- Perfect for debug modes, logging control, and dynamic optimizations
155+
- Automatically cleared when the process ends
156+
157+
```php
158+
// Skip cache during testing
159+
memoize()->enableFlag('bypass_cache');
160+
161+
$userData = memoize()->memo("user_{$id}", function() use ($id) {
162+
if (memoize()->hasFlag('bypass_cache')) {
163+
return User::fresh()->find($id); // Always fetch from DB in tests
164+
}
165+
return User::find($id);
166+
});
167+
168+
169+
// Feature toggles without external dependencies
170+
memoize()->enableFlag('new_algorithm');
171+
172+
$result = memoize()->memo($cacheKey, function() {
173+
if (memoize()->hasFlag('new_algorithm')) {
174+
return $this->calculateWithNewAlgorithm();
175+
}
176+
return $this->calculateWithOldAlgorithm();
177+
});
178+
179+
// Development vs Production behavior
180+
if (app()->environment('local') && memoize()->hasFlag('dev_mode')) {
181+
memoize()->enableFlags(['verbose_logging', 'bypass_cache']);
182+
}
183+
184+
// Model boot method with conditional service calls
185+
class Product extends Model
186+
{
187+
protected static function boot()
188+
{
189+
parent::boot();
190+
191+
static::updated(function ($product) {
192+
// Only call external stock service if flag is not set
193+
if (! memoize()->hasFlag('disableStockService')) {
194+
app(StockService::class)->updateInventory($product);
195+
}
196+
});
197+
}
198+
}
199+
```
200+
201+
**Runtime Flag Methods:**
202+
203+
<table>
204+
<tr><td width="40%"><strong>Method</strong></td><td><strong>Description</strong></td></tr>
205+
<tr><td>
206+
207+
**enableFlag(string $flag)**
208+
209+
</td><td>Enable a specific runtime flag</td></tr>
210+
<tr><td>
211+
212+
**disableFlag(string $flag)**
213+
214+
</td><td>Disable a specific runtime flag</td></tr>
215+
<tr><td>
216+
217+
**toggleFlag(string $flag)**
218+
219+
</td><td>Toggle flag state (enabled/disabled)</td></tr>
220+
<tr><td>
221+
222+
**hasFlag(string $flag): bool**
223+
224+
</td><td>Check if a specific flag is enabled</td></tr>
225+
<tr><td>
226+
227+
**enableFlags(array $flags)**
228+
229+
</td><td>Enable multiple flags at once</td></tr>
230+
<tr><td>
231+
232+
**disableFlags(array $flags)**
233+
234+
</td><td>Disable multiple flags at once</td></tr>
235+
<tr><td>
236+
237+
**hasAnyFlag(array $flags): bool**
238+
239+
</td><td>Check if at least one flag is enabled</td></tr>
240+
<tr><td>
241+
242+
**hasAllFlags(array $flags): bool**
243+
244+
</td><td>Check if all specified flags are enabled</td></tr>
245+
<tr><td>
246+
247+
**getFlags(): array**
248+
249+
</td><td>Get all currently enabled flags</td></tr>
250+
<tr><td>
251+
252+
**clearFlags()**
253+
254+
</td><td>Clear all enabled flags</td></tr>
255+
</table>
256+
147257
## 💡 **Advanced Examples**
148258

149259
### 🏃‍♂️ **Performance Optimization**

src/Concerns/HasFlags.php

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tomloprod\Memoize\Concerns;
6+
7+
/**
8+
* Trait for handling flag-related functionalities.
9+
*/
10+
trait HasFlags
11+
{
12+
/** @var array<string, bool> */
13+
private array $enabledFlags = [];
14+
15+
/**
16+
* Enable a specific flag.
17+
*/
18+
public function enableFlag(string $flag): self
19+
{
20+
$this->enabledFlags[$flag] = true;
21+
22+
return $this;
23+
}
24+
25+
/**
26+
* Disable a specific flag.
27+
*/
28+
public function disableFlag(string $flag): self
29+
{
30+
unset($this->enabledFlags[$flag]);
31+
32+
return $this;
33+
}
34+
35+
/**
36+
* Toggle the state of a flag (enabled/disabled).
37+
*/
38+
public function toggleFlag(string $flag): self
39+
{
40+
if (isset($this->enabledFlags[$flag])) {
41+
unset($this->enabledFlags[$flag]);
42+
} else {
43+
$this->enabledFlags[$flag] = true;
44+
}
45+
46+
return $this;
47+
}
48+
49+
/**
50+
* Check if a specific flag is enabled.
51+
*/
52+
public function hasFlag(string $flag): bool
53+
{
54+
return isset($this->enabledFlags[$flag]);
55+
}
56+
57+
/**
58+
* Get all currently enabled flags.
59+
*
60+
* @return array<string, bool> Associative array with enabled flags
61+
*/
62+
public function getFlags(): array
63+
{
64+
return $this->enabledFlags;
65+
}
66+
67+
/**
68+
* Enable multiple flags at once.
69+
*
70+
* @param array<string> $flags Array of flag names to enable
71+
*/
72+
public function enableFlags(array $flags): self
73+
{
74+
foreach ($flags as $flag) {
75+
$this->enabledFlags[$flag] = true;
76+
}
77+
78+
return $this;
79+
}
80+
81+
/**
82+
* Disable multiple flags at once.
83+
*
84+
* @param array<string> $flags Array of flag names to disable
85+
*/
86+
public function disableFlags(array $flags): self
87+
{
88+
foreach ($flags as $flag) {
89+
unset($this->enabledFlags[$flag]);
90+
}
91+
92+
return $this;
93+
}
94+
95+
/**
96+
* Clear all enabled flags.
97+
*/
98+
public function clearFlags(): self
99+
{
100+
$this->enabledFlags = [];
101+
102+
return $this;
103+
}
104+
105+
/**
106+
* Check if at least one of the specified flags is enabled.
107+
*
108+
* @param array<string> $flags Array of flag names to check
109+
*/
110+
public function hasAnyFlag(array $flags): bool
111+
{
112+
foreach ($flags as $flag) {
113+
if (isset($this->enabledFlags[$flag])) {
114+
return true;
115+
}
116+
}
117+
118+
return false;
119+
}
120+
121+
/**
122+
* Check if all specified flags are enabled.
123+
*
124+
* @param array<string> $flags Array of flag names to check
125+
*/
126+
public function hasAllFlags(array $flags): bool
127+
{
128+
foreach ($flags as $flag) {
129+
if (! isset($this->enabledFlags[$flag])) {
130+
return false;
131+
}
132+
}
133+
134+
return true;
135+
}
136+
}

src/Services/MemoizeManager.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@
66

77
use Exception;
88
use InvalidArgumentException;
9+
use Tomloprod\Memoize\Concerns\HasFlags;
910

1011
final class MemoizeManager
1112
{
13+
use HasFlags;
14+
1215
private static MemoizeManager $instance;
1316

1417
/** @var array<string, MemoEntry> */

src/Support/Facades/Memoize.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,16 @@
1818
* @method static ?int getMaxSize()
1919
* @method static array getStats()
2020
* @method static self for(string $class)
21+
* @method static self enableFlag(string $flag)
22+
* @method static self disableFlag(string $flag)
23+
* @method static self toggleFlag(string $flag)
24+
* @method static bool hasFlag(string $flag)
25+
* @method static array<string, bool> getFlags()
26+
* @method static self enableFlags(array $flags)
27+
* @method static self disableFlags(array $flags)
28+
* @method static self clearFlags()
29+
* @method static bool hasAnyFlag(array $flags)
30+
* @method static bool hasAllFlags(array $flags)
2131
*/
2232
final class Memoize
2333
{

0 commit comments

Comments
 (0)