PHPackages                             caseyamcl/settings-manager - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. caseyamcl/settings-manager

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

caseyamcl/settings-manager
==========================

Settings Manager

v1.1(4y ago)21331[1 issues](https://github.com/caseyamcl/settings-manager/issues)[1 PRs](https://github.com/caseyamcl/settings-manager/pulls)MITPHPPHP ^7.3|^8.0

Since Aug 16Pushed 4y ago1 watchersCompare

[ Source](https://github.com/caseyamcl/settings-manager)[ Packagist](https://packagist.org/packages/caseyamcl/settings-manager)[ Docs](https://github.com/caseyamcl/settings-manager)[ RSS](/packages/caseyamcl-settings-manager/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (7)Dependencies (2)Versions (8)Used By (0)

Settings Manager
================

[](#settings-manager)

[![Latest Version on Packagist](https://camo.githubusercontent.com/18f1196f54dc97b5f79427de4e624c4f4edd9b625060a1f30277dcddbd164cb8/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6361736579616d636c2f73657474696e67732d6d616e616765722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/caseyamcl/settings-manager)[![Software License](https://camo.githubusercontent.com/55c0218c8f8009f06ad4ddae837ddd05301481fcf0dff8e0ed9dadda8780713e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d627269676874677265656e2e7376673f7374796c653d666c61742d737175617265)](LICENSE.md)[![Build Status](https://camo.githubusercontent.com/2db8905b77293cbab787fd4e79e8ccf27024c8f4bfad7fc16f5948db3c68d9d9/68747470733a2f2f696d672e736869656c64732e696f2f7472617669732f6361736579616d636c2f73657474696e67732d6d616e616765722f6d61737465722e7376673f7374796c653d666c61742d737175617265)](https://travis-ci.org/caseyamcl/settings-manager)[![Coverage Status](https://camo.githubusercontent.com/9284b59031e809577b93b9306a0b67635b7e396a6d0b4d43b514be0d5ff3b58f/68747470733a2f2f696d672e736869656c64732e696f2f7363727574696e697a65722f636f7665726167652f672f6361736579616d636c2f73657474696e67732d6d616e616765722e7376673f7374796c653d666c61742d737175617265)](https://scrutinizer-ci.com/g/caseyamcl/settings-manager/code-structure)[![Quality Score](https://camo.githubusercontent.com/bd9f5d676659fc384d2cb065d55668b290658e1d1c7749ff242be210c26d8054/68747470733a2f2f696d672e736869656c64732e696f2f7363727574696e697a65722f672f6361736579616d636c2f73657474696e67732d6d616e616765722e7376673f7374796c653d666c61742d737175617265)](https://scrutinizer-ci.com/g/caseyamcl/settings-manager)[![Total Downloads](https://camo.githubusercontent.com/478378763d16917339a79394db99377b30febc4eb1a520c7771d9d729d7b8d75/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6361736579616d636c2f73657474696e67732d6d616e616765722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/caseyamcl/settings-manager)

This is a framework-agnostic library that provides an abstraction for managing and storing user-changeable settings. Settings can be stored in a configuration file, database, external API or anywhere else. The defining characteristic of this library is designed around the assumption that settings will be modified during runtime, which makes it particularly useful for increasingly popular architectures such as [Swoole](https://www.swoole.co.uk/), [React](https://reactphp.org/), etc.

It provides the following features:

- Class-based setting definitions
- Ability to define multiple providers for settings and load them in a cascading manner
- Ability to validate and prepare/transform setting values
- PSR-4 and PSR-12 compliance; 100% unit test coverage

What is a setting?
------------------

[](#what-is-a-setting)

This library is useful for projects that make a clear distinction between configuration values (set by administrators) and settings (available in the app; changeable by users during runtime):

Configuration ValueSettingSet on the command line in a YAML/JSON/INI file or environment variable during application setupSet in the application's API or web interfaceManaged by system administrator or developerManaged by application userNot likely to ever changeMutable and able to change during runtimeShould be set before application can be executedNot necessary during app bootstrapConcepts
--------

[](#concepts)

A **Setting Definition** is simply a PHP class that implements the `SettingDefinition` interface. A setting definition has the following attributes:

- A name (e.g. a machine name/slug)
- A display name
- Internal notes
- An optional default value
- Optional validation/transform logic for processing incoming values
- Whether or not this value is sensitive (e.g. should be treated securely)

Setting definitions are added to an instance of the `SettingDefinitionRegistry`.

A **Setting Provider** is a service class that loads setting values from a source. Sources can be configuration files, databases, or really anything. See the [usage](#usage) section below for a list of bundled providers.

Multiple providers can be chained together so that setting values are loaded in a cascading way. Several providers have been bundled (see below), but you can feel free to add your own by implementing the `SettingProvider` interface. Providers have similar attributes to definitions:

- A name (e.g. a machine name/slug)
- A display name

A **Setting Value** is an object that stores the value of the setting, along with a few additional bits of information:

- The setting name
- The provider name that this setting came was defined by
- Mutability - whether this setting can be overridden after this provider (e.g. an administrator may want to lock a setting in-place in a configuration file and not allow a downstream provider to change it)

Install
-------

[](#install)

Via Composer

```
$ composer require caseyamcl/settings-manager
```

Usage
-----

[](#usage)

### Basic Usage

[](#basic-usage)

Basic usage of this library consists of two steps:

1. Defining setting definitions
2. Loading setting values from providers

#### Defining setting definitions

[](#defining-setting-definitions)

The recommended way to create settings is for each setting definition to be its own class. While this isn't strictly necessary (you can create any class that implements `SettingDefinition`), it does keep things clean and simple.

For convenience, this library includes the `AbstractSettingDefinition` class, which includes constants for common attributes. See the following example:

```
use SettingsManager\Model\AbstractSettingDefinition;
use SettingsManager\Exception\InvalidSettingValueException;
use SettingsManager\Registry\SettingDefinitionRegistry;

// 1. Create setting definition:

/**
 * Settings must implement the SettingDefinition interface.
 *
 * For convenience, an AbstractSettingDefinition class is bundled with the library.
 */
class MySetting extends AbstractSettingDefinition
{
    // Required; This is the machine name, and it is recommended that you stick to machine-friendly names (alpha-dash, underscore)
    public const NAME = 'my_setting';

    // Required; This is the "human friendly" name for the setting
    public const DISPLAY_NAME = 'My Setting';

    // Internal notes (optional)
    public const NOTES = "These are notes that are either available to all users or just admins (implementor's choice)";

    // Set an optional default (may need to override the getDefault() method if complex logic is required)
    public const DEFAULT = null;

    // Indicate whether this value is sensitive or not.  By default, this is set to TRUE
    // This is relevant if the application wants to expose some setting values to all users, while hiding other ones
    public const SENSITIVE = true;

    /**
     * If there is any validation for this setting, you can override the processValue() method
     *
     * Throw an InvalidSettingValueException in the case of an invalid value
     *
     * @param string $value
     * @return string
     */
    public function processValue($value)
    {
        if (! is_string($value)) {
            $errors[] = "value must be a string";
        }
        if ($value !== 'test') {
            $errors[] = "value must be equal to 'test'";
        }

        if (! empty($errors)) {
            // InvalidSettingValueException allows for multiple error messages
            throw new InvalidSettingValueException($errors);
        }

        return $value;
    }
}

// 2. Add it to the registry:

$registry = new SettingDefinitionRegistry();
$registry->add(new MySetting());
// etc.  add more values...
```

#### Loading setting values from providers

[](#loading-setting-values-from-providers)

Setting values are loaded from setting providers. There are a few bundled providers included in this library, and you can create your own by implementing the `SettingsManager\Contract\SettingProvider` interface.

In this example, we use the `CascadingSettingProvider` to combine the functionality of the `DefaultValuesProvider` and the `ArrayValuesProvider`:

```
use SettingsManager\Provider\CascadingSettingProvider;
use SettingsManager\Provider\DefaultValuesProvider;
use SettingsManager\Provider\ArrayValuesProvider;
use SettingsManager\Registry\SettingDefinitionRegistry;

// Setup a registry and add settings to it...
$registry = new SettingDefinitionRegistry();
$registry->add(new MySetting());

// An array of setting values
$settingValues = [
    'my_setting' => 'test'
];

// Setup the provider
$provider = new CascadingSettingProvider([
    new DefaultValuesProvider($registry), // loads default values
    new ArrayValuesProvider($settingValues, $registry), // loads values from an array
]);

// Get values from the provider..
$provider->findValue('my_setting'); // returns 'test'
$provider->getValue('my_setting'); // returns 'test' (would throw an exception if value isn't defined)

// If you want to get the `SettingValue` instance (with metadata), use
// `findValueInstance` or `getValueInstance`
$provider->getValueInstance('my_setting')->getValue();
$provider->findValueInstance('my_setting')->getValue();

// `getValue` throws an exception if the requested setting isn't defined
$provider->getValue('non_existent_value'); // Throws UndefinedSettingException

// `findValue()` returns NULL if the requested setting isn't defined
$provider->findValue('non_existent_value'); // returns NULL
```

### Bundled providers

[](#bundled-providers)

Basic setting providers are bundled with this library in the `SettingsManager\Provider` namespace:

ProviderWhat it does`ArrayValuesProvider`Loads values from an array`DefaultValuesProvider`Loads default values`CascadingSettingProvider`Loads from multiple providers`SettingRepositoryProvider`Loads values from a database or repository (see below)### Setting mutability

[](#setting-mutability)

Sometimes you want settings to be "locked" by a certain provider. For example, if you want a setting to be unchangeable after a certain provider has loaded it (say, a configuration file), you can use the following syntax:

```
use SettingsManager\Provider\ArrayValuesProvider;
use SettingsManager\Provider\DefaultValuesProvider;
use SettingsManager\Provider\SettingRepositoryProvider;
use SettingsManager\Provider\CascadingSettingProvider;
use SettingsManager\Registry\SettingDefinitionRegistry;
use MyApp\MySettingRepository;
use MyApp\SensitivePasswordSetting;

// Setup a registry and add settings to it...
$registry = new SettingDefinitionRegistry();
$registry->add(new SensitivePasswordSetting());

// Method #1 - Key/value pairs
$values = [
    'sensitive_password' => '11111',
    'another_setting' => 123,
    // etc..
];

// Method #2
$values = [
    'sensitive_password' => [
        'value'   => '11111',
        'mutable' => false // downstream providers won't be able to override this setting
    ],
    'another_setting' => [
       'value'    => 123,
       'mutable'  => true // downstream providers WILL be able to override this setting
    ]
];

// Mix and match methods #1 and #2
$values = [
    'sensitive_password' => '11111',
    'another_setting' => [
       'value'    => 123,
       'mutable'  => true
    ]
];

$provider = CascadingSettingProvider::build(
    new DefaultValuesProvider($registry),
    new ArrayValuesProvider($values, $registry, 'config_file'),
    new SettingRepositoryProvider(new MySettingRepository())
);

$provider->getValueInstance('sensitive_password')->getProviderName(); // will always be 'config_file'
```

### Creating your own provider implementation using the `SettingRepositoryProvider`

[](#creating-your-own-provider-implementation-using-the-settingrepositoryprovider)

Chances are, you'll want to store values in a database. For convenience, a `SettingRepository` interface has been bundled as part of this package, along with a `SettingRepositoryProvider`.

```
use SettingsManager\Contract\SettingRepository;
use SettingsManager\Exception\SettingValueNotFoundException;
use SettingsManager\Provider\SettingRepositoryProvider;

class MySettingRepository implements SettingRepository
{
    /**
     * @var MyDatabaseProvider
     */
    private $dbConnection;

    /**
     * MySettingRepository constructor.
     * @param MyDatabaseProvider $dbConnection
     */
    public function __construct(MyDatabaseProvider $dbConnection)
    {
        $this->dbConnection = $dbConnection;
    }

    /**
     * Find a setting value by its name or NULL if it is not found
     *
     * @param string $settingName
     * @return mixed|null
     */
    public function findValue(string $settingName)
    {
        return $this->dbConnection->findValue($settingName);
    }

    /**
     * Get a setting value by its name or throw an exception if not found
     *
     * @param string $settingName
     * @return mixed
     * @throws SettingValueNotFoundException
     */
    public function getValue(string $settingName)
    {
        if ($this->dbConnection->hasValue($settingName)) {
            return $this->findValue($settingName);
        } else {
            throw SettingValueNotFoundException::fromName($settingName);
        }
    }

    /**
     * List values
     *
     * @return iterable|mixed[]
     */
    public function listValues(): iterable
    {
        return $this->dbConnection->listValues();
    }
}

// Then, use the `SettingRepositoryProvider`
$repository = new MySettingRepository($dbConn);
$provider = new SettingRepositoryProvider($repository);
```

### Handling Exceptions

[](#handling-exceptions)

Exceptions all implement the `SettingException` interface:

ExceptionWhat causes it`ImmutableSettingOverrideException`If a provider has defined a setting as immutable, and a subsequent provider attempts to override it`InvalidSettingValueException`This should be thrown in the case of validation errors`UndefinedSettingException`This is thrown from a provider when attempting when attempting to load a setting that hasn't been added to the registry`SettingNameCollissionException`This is thrown when attempting to add two definitions to the registry with the same name`SettingValueNotFoundException`This is thrown when calling `getValue()` or `getValueInstance()` from a provider on a non-existent setting### Considerations for runtime environments

[](#considerations-for-runtime-environments)

This library facilitates environments such as those provided by Swoole or React in which setting values are updated at runtime.

If you want to enable this functionality, be sure to always inject whatever setting provider you are using in your service classes, and lookup settings **during runtime**.

```
use SettingsManager\Contract\SettingProvider;

class MyServiceClass {

    /**
     * @var SettingProvider
     */
    private $settings;

    /**
     * MyServiceClass constructor.
     * @param SettingProvider $provider
     */
    public function __construct(SettingProvider $provider)
    {
        $this->settings = $provider;
    }

    public function doSomethingThatRequiresLookingUpASetting(): void
    {
        // Always lookup the setting value during runtime
        $settingValue = $this->settings->getValue('some_setting');

        // do stuff here..
    }
}
```

Change log
----------

[](#change-log)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

Testing
-------

[](#testing)

```
$ composer test
```

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](CONTRIBUTING.md) and [CODE\_OF\_CONDUCT](CODE_OF_CONDUCT.md) for details.

Security
--------

[](#security)

If you discover any security related issues, please email  instead of using the issue tracker.

Credits
-------

[](#credits)

- [Casey McLaughlin](https://github.com/caseyamcl)
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

30

—

LowBetter than 64% of packages

Maintenance10

Infrequent updates — may be unmaintained

Popularity15

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity72

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~212 days

Recently: every ~311 days

Total

7

Last Release

1557d ago

Major Versions

v0.9 → v1.02019-10-28

PHP version history (3 changes)v0.1PHP ^7.1

v0.9PHP ^7.2

v1.1PHP ^7.3|^8.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/8db51cd614310a5de4822be9602de578e6d6dd2af7949d52fcd375ba2a8d1c74?d=identicon)[caseyamcl](/maintainers/caseyamcl)

---

Top Contributors

[![caseyamcl](https://avatars.githubusercontent.com/u/53035?v=4)](https://github.com/caseyamcl "caseyamcl (45 commits)")

---

Tags

Settingscaseyamclsettings\_manager

###  Code Quality

TestsPHPUnit

Code StylePHP\_CodeSniffer

### Embed Badge

![Health badge](/badges/caseyamcl-settings-manager/health.svg)

```
[![Health](https://phpackages.com/badges/caseyamcl-settings-manager/health.svg)](https://phpackages.com/packages/caseyamcl-settings-manager)
```

###  Alternatives

[akaunting/laravel-setting

Persistent settings package for Laravel

495805.1k7](/packages/akaunting-laravel-setting)[outl1ne/nova-settings

A Laravel Nova tool for editing custom settings using native Nova fields.

296883.2k3](/packages/outl1ne-nova-settings)[chillerlan/php-settings-container

A container class for immutable settings objects. Not a DI container.

3427.3M21](/packages/chillerlan-php-settings-container)[codeigniter4/settings

Settings library for CodeIgniter 4

93499.3k24](/packages/codeigniter4-settings)[dmishh/settings-bundle

Database centric Symfony configuration management. Global and per-user settings supported.

115254.9k1](/packages/dmishh-settings-bundle)[zachleigh/laravel-property-bag

Easy Laravel user settings using a property bag

85340.3k](/packages/zachleigh-laravel-property-bag)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
