Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 118 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# Configuration

To make changes to the config file, you need to have your own copy in `app/Config/Settings.php`. The easiest way to do it is by using the publish command.

When you run:

php spark settings:publish

You will get your copy ready for modifications.

---

## Handlers

An array of handler aliases to use for storing and retrieving settings. Handlers are checked in order, with the first handler that has a value returning it.

**Type:** `array`

**Default:** `['database']`

**Available handlers:** `database`, `file`, `array`

Example:

```php
public $handlers = ['database'];
```
### Multiple handlers

When multiple handlers are configured, they are checked in the order specified in $handlers. The first handler that has a value for the requested setting will return it.

Example with fallback:

```php
public $handlers = ['file', 'database'];
```
This configuration will:

1. Check the file handler first
2. If not found, check the database handler
3. If not found in any handler, return the default value from the config file

### Writeable Handlers

Only handlers marked as `writeable => true` will be used when calling `set()`, `forget()`, or `flush()` methods.

## DatabaseHandler

This handler stores settings in a database table and is production-ready for high-traffic applications.

**Available options:**

* `class` - The handler class. Default: `DatabaseHandler::class`
* `table` - The database table name for storing settings. Default: `'settings'`
* `group` - The database connection group to use. Default: `null` (uses default connection)
* `writeable` - Whether this handler supports write operations. Default: `true`

Example:

```php
public $database = [
'class' => DatabaseHandler::class,
'table' => 'settings',
'group' => null,
'writeable' => true,
];
```

!!! note
You need to run migrations to create the settings table: `php spark migrate -n CodeIgniter\\Settings`

---

## FileHandler

This handler stores settings as PHP files and is optimized for production use with built-in race condition protection.

**Available options:**

* `class` - The handler class. Default: `FileHandler::class`
* `path` - The directory path where settings files are stored. Default: `WRITEPATH . 'settings'`
* `writeable` - Whether this handler supports write operations. Default: `true`

Example:

```php
public $file = [
'class' => FileHandler::class,
'path' => WRITEPATH . 'settings',
'writeable' => true,
];
```

!!! note
The `FileHandler` automatically creates the directory if it doesn't exist and checks write permissions on instantiation.

---

## ArrayHandler

This handler stores settings in memory only and is primarily useful for testing or as a parent class for other handlers.

**Available options:**

* `class` - The handler class. Default: `ArrayHandler::class`
* `writeable` - Whether this handler supports write operations. Default: `true`

Example:

```php
public $array = [
'class' => ArrayHandler::class,
'writeable' => true,
];
```

!!! note
`ArrayHandler` does not persist data between requests. It's mainly used for testing or extended by other handlers.
4 changes: 2 additions & 2 deletions docs/limitations.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

The following are known limitations of the library:

1. You can currently only store a single setting at a time. While the `DatabaseHandler` uses a local cache to
keep performance as high as possible for reads, writes must be done one at a time.
1. You can currently only store a single setting at a time. While the `DatabaseHandler` and `FileHandler`
uses a local cache to keep performance as high as possible for reads, writes must be done one at a time.
2. You can only access the first level within a property directly. In most config classes this is a non-issue,
since the properties are simple values. Some config files, like the `database` file, contain properties that
are arrays.
3 changes: 2 additions & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ extra:
site_url: https://settings.codeigniter.com/
repo_url: https://github.com/codeigniter4/settings
edit_uri: edit/develop/docs/
copyright: Copyright © 2023 CodeIgniter Foundation.
copyright: Copyright © 2025 CodeIgniter Foundation.

markdown_extensions:
- admonition
Expand All @@ -73,5 +73,6 @@ extra_javascript:
nav:
- Home: index.md
- Installation: installation.md
- Configuration: configuration.md
- Basic usage: basic-usage.md
- Limitations: limitations.md
51 changes: 47 additions & 4 deletions src/Commands/ClearSettings.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,61 @@

class ClearSettings extends BaseCommand
{
protected $group = 'Housekeeping';
protected $group = 'Settings';
protected $name = 'settings:clear';
protected $description = 'Clears all settings from the database.';
protected $description = 'Clears all settings from persistent storage.';

public function run(array $params)
{
if (CLI::prompt('This will delete all settings from the database. Are you sure you want to continue?', ['y', 'n'], 'required') !== 'y') {
$config = config('Settings');
$handlers = $this->getHandlerNames($config);

if ($handlers === null) {
CLI::write('No handlers available to clear in the config file.');

return;
}

if (CLI::prompt('This will delete all settings from ' . $handlers . '. Are you sure you want to continue?', ['y', 'n'], 'required') !== 'y') {
return;
}

service('settings')->flush();

CLI::write('Settings cleared from the database.', 'green');
CLI::write('Settings cleared from ' . $handlers . '.', 'green');
}

/**
* Gets a human-readable list of handler names.
*
* @param mixed $config
*/
private function getHandlerNames($config): ?string
{
if ($config->handlers === []) {
return null;
}

$handlerNames = [];

foreach ($config->handlers as $handler) {
// Get writeable handlers only (those that can be flushed)
if (isset($config->{$handler}['writeable']) && $config->{$handler}['writeable'] === true) {
$handlerNames[] = $handler;
}
}

if ($handlerNames === []) {
return null;
}

if (count($handlerNames) === 1) {
return $handlerNames[0] . ' handler';
}

// Multiple handlers: "database and file"
$last = array_pop($handlerNames);

return implode(', ', $handlerNames) . ' and ' . $last . ' handlers';
}
}
53 changes: 53 additions & 0 deletions src/Commands/PublishSettings.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

declare(strict_types=1);

/**
* This file is part of CodeIgniter Queue.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

namespace CodeIgniter\Settings\Commands;

use CodeIgniter\CLI\BaseCommand;
use CodeIgniter\CLI\CLI;
use CodeIgniter\Publisher\Publisher;
use Throwable;

class PublishSettings extends BaseCommand
{
protected $group = 'Settings';
protected $name = 'settings:publish';
protected $description = 'Publish Settings config file into the current application.';

public function run(array $params): void
{
$source = service('autoloader')->getNamespace('CodeIgniter\\Settings')[0];

$publisher = new Publisher($source, APPPATH);

try {
$publisher->addPaths([
'Config/Settings.php',
])->merge(false);
} catch (Throwable $e) {
$this->showError($e);

return;
}

foreach ($publisher->getPublished() as $file) {
$contents = file_get_contents($file);
$contents = str_replace('namespace CodeIgniter\\Settings\\Config', 'namespace Config', $contents);
$contents = str_replace('use CodeIgniter\\Config\\BaseConfig', 'use CodeIgniter\\Settings\\Config\\Settings as BaseSettings', $contents);
$contents = str_replace('class Settings extends BaseConfig', 'class Settings extends BaseSettings', $contents);
file_put_contents($file, $contents);
}

CLI::write(CLI::color(' Published! ', 'green') . 'You can customize the configuration by editing the "app/Config/Settings.php" file.');
}
}
10 changes: 10 additions & 0 deletions src/Config/Settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Settings\Handlers\ArrayHandler;
use CodeIgniter\Settings\Handlers\DatabaseHandler;
use CodeIgniter\Settings\Handlers\FileHandler;

class Settings extends BaseConfig
{
Expand Down Expand Up @@ -34,4 +35,13 @@ class Settings extends BaseConfig
'group' => null,
'writeable' => true,
];

/**
* File handler settings.
*/
public $file = [
'class' => FileHandler::class,
'path' => WRITEPATH . 'settings',
'writeable' => true,
];
}
14 changes: 14 additions & 0 deletions src/Handlers/ArrayHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,18 @@ protected function forgetStored(string $class, string $property, ?string $contex
unset($this->contexts[$context][$class][$property]);
}
}

/**
* Retrieves all stored properties for a specific class and context.
*
* @return array<string,array> Format: ['property' => ['value', 'type']]
*/
protected function getAllStored(string $class, ?string $context): array
{
if ($context === null) {
return $this->general[$class] ?? [];
}

return $this->contexts[$context][$class] ?? [];
}
}
Loading
Loading