Skip to content

Commit 706a170

Browse files
committed
feat(settings): add batch setting operations
Signed-off-by: memleakd <[email protected]>
1 parent f0cd3e2 commit 706a170

10 files changed

Lines changed: 737 additions & 52 deletions

docs/basic-usage.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,32 @@ when retrieved.
3030
service('settings')->set('App.siteName', 'My Great Site');
3131
```
3232

33+
You can save multiple values with `setMany()`. This behaves like calling `set()` for each key/value pair,
34+
but allows supported handlers to persist the changes more efficiently.
35+
36+
```php
37+
service('settings')->setMany([
38+
'App.siteName' => 'My Great Site',
39+
'App.siteEmail' => '[email protected]',
40+
]);
41+
```
42+
3343
You can delete a value from the persistent storage with the `forget()` method. Since it is removed from the storage,
3444
it effectively resets itself back to the default value in config file, if any.
3545

3646
```php
3747
service('settings')->forget('App.siteName');
3848
```
3949

50+
You can delete multiple values with `forgetMany()`.
51+
52+
```php
53+
service('settings')->forgetMany([
54+
'App.siteName',
55+
'App.siteEmail',
56+
]);
57+
```
58+
4059
If you ever need to completely remove all settings from their persistent storage, you can use the `flush()` method. This immediately removes all settings from the database and the in-memory cache.
4160

4261
```php
@@ -62,6 +81,16 @@ $context = 'user:' . user_id();
6281
service('settings')->set('App.theme', 'dark', $context);
6382
```
6483

84+
The same context can be applied to a batch of values:
85+
86+
```php
87+
$context = 'user:' . user_id();
88+
service('settings')->setMany([
89+
'App.theme' => 'dark',
90+
'App.locale' => 'en',
91+
], $context);
92+
```
93+
6594
Now when your filter is determining which theme to apply it can check for the current user as the context:
6695

6796
```php
@@ -91,9 +120,17 @@ setting('App.siteName', 'My Great Site');
91120
// Using the service through the helper
92121
$name = setting()->get('App.siteName');
93122
setting()->set('App.siteName', 'My Great Site');
123+
setting()->setMany([
124+
'App.siteName' => 'My Great Site',
125+
'App.siteEmail' => '[email protected]',
126+
]);
94127

95128
// Forgetting a value
96129
setting()->forget('App.siteName');
130+
setting()->forgetMany([
131+
'App.siteName',
132+
'App.siteEmail',
133+
]);
97134
```
98135

99136
!!! Note

docs/configuration.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ Handlers like `database` and `file` support deferred writes. When `deferWrites`
3232
are batched and persisted efficiently at the end of the request during the `post_system` event. This minimizes the number of
3333
database queries or file I/O operations, improving performance for write-heavy operations.
3434

35+
This is separate from the explicit `setMany()` and `forgetMany()` APIs. Batch APIs allow callers to group multiple settings in
36+
one method call, while deferred writes decide whether writes are persisted immediately or at the end of the request.
37+
3538
### Multiple handlers
3639

3740
Example:
@@ -94,6 +97,16 @@ $settings->set('Example.prop3', 'value3');
9497

9598
The deferred approach is especially beneficial when updating existing records or performing many operations in a single request.
9699

100+
For explicit batches, use `setMany()` or `forgetMany()`:
101+
102+
```php
103+
$settings->setMany([
104+
'Example.prop1' => 'value1',
105+
'Example.prop2' => 'value2',
106+
'Example.prop3' => 'value3',
107+
]);
108+
```
109+
97110
---
98111

99112
## FileHandler
@@ -136,6 +149,16 @@ $settings->set('Example.prop3', 'value3');
136149

137150
The deferred approach is especially beneficial when updating multiple properties in the same class.
138151

152+
For explicit batches, use `setMany()` or `forgetMany()`:
153+
154+
```php
155+
$settings->setMany([
156+
'Example.prop1' => 'value1',
157+
'Example.prop2' => 'value2',
158+
'Example.prop3' => 'value3',
159+
]);
160+
```
161+
139162
---
140163

141164
## ArrayHandler

docs/limitations.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ The following are known limitations of the library:
55
1. **Immediate writes (`deferWrites => false`)**: Each setting is written to storage immediately when you call `set()` or `forget()`.
66
The first operation hydrates all settings for that context (1 SELECT query), then each subsequent write performs a separate
77
INSERT or UPDATE. While `DatabaseHandler` and `FileHandler` use an in-memory cache to maintain fast reads, individual write
8-
operations may result in multiple database queries or file writes per request.
8+
operations may result in multiple database queries or file writes per request. Use `setMany()` or `forgetMany()` when you
9+
want to explicitly persist multiple settings in one batch operation.
910

1011
2. **Deferred writes (`deferWrites => true`)**: All settings are batched and written to storage at the end of the request
1112
(during the `post_system` event). This minimizes the number of database queries and file writes, improving performance.

src/Handlers/BaseHandler.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,21 @@ public function set(string $class, string $property, $value = null, ?string $con
3535
throw new RuntimeException('Set method not implemented for current Settings handler.');
3636
}
3737

38+
/**
39+
* If the Handler supports saving values, it MAY override this method
40+
* to provide optimized batch functionality.
41+
*
42+
* @param list<array{class: string, property: string, value: mixed}> $settings
43+
*
44+
* @throws RuntimeException
45+
*/
46+
public function setMany(array $settings, ?string $context = null): void
47+
{
48+
foreach ($settings as $setting) {
49+
$this->set($setting['class'], $setting['property'], $setting['value'], $context);
50+
}
51+
}
52+
3853
/**
3954
* If the Handler supports forgetting values, it
4055
* MUST override this method to provide that functionality.
@@ -48,6 +63,21 @@ public function forget(string $class, string $property, ?string $context = null)
4863
throw new RuntimeException('Forget method not implemented for current Settings handler.');
4964
}
5065

66+
/**
67+
* If the Handler supports forgetting values, it MAY override this method
68+
* to provide optimized batch functionality.
69+
*
70+
* @param list<array{class: string, property: string}> $settings
71+
*
72+
* @throws RuntimeException
73+
*/
74+
public function forgetMany(array $settings, ?string $context = null): void
75+
{
76+
foreach ($settings as $setting) {
77+
$this->forget($setting['class'], $setting['property'], $context);
78+
}
79+
}
80+
5181
/**
5282
* All handlers MUST support flushing all values.
5383
*

0 commit comments

Comments
 (0)