{"id":15525359,"url":"https://github.com/ghostwriter/config","last_synced_at":"2025-11-19T11:03:05.550Z","repository":{"id":65151069,"uuid":"584202366","full_name":"ghostwriter/config","owner":"ghostwriter","description":"Provides an object that maps configuration keys to values.","archived":false,"fork":false,"pushed_at":"2025-11-01T20:05:42.000Z","size":844,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"2.0.x","last_synced_at":"2025-11-01T20:18:47.295Z","etag":null,"topics":["config","configuration","ghostwriter"],"latest_commit_sha":null,"homepage":"https://github.com/ghostwriter/config","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ghostwriter.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["ghostwriter"]}},"created_at":"2023-01-01T20:11:50.000Z","updated_at":"2025-11-01T20:05:43.000Z","dependencies_parsed_at":"2025-11-19T11:01:45.191Z","dependency_job_id":null,"html_url":"https://github.com/ghostwriter/config","commit_stats":{"total_commits":67,"total_committers":1,"mean_commits":67.0,"dds":0.0,"last_synced_commit":"40665c55154ac7a6d1e080f083ac2ca5907a0748"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":"ghostwriter/package-template","purl":"pkg:github/ghostwriter/config","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ghostwriter%2Fconfig","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ghostwriter%2Fconfig/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ghostwriter%2Fconfig/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ghostwriter%2Fconfig/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ghostwriter","download_url":"https://codeload.github.com/ghostwriter/config/tar.gz/refs/heads/2.0.x","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ghostwriter%2Fconfig/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":285231775,"owners_count":27136520,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-11-19T02:00:05.673Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["config","configuration","ghostwriter"],"created_at":"2024-10-02T10:57:03.334Z","updated_at":"2025-11-19T11:03:05.539Z","avatar_url":"https://github.com/ghostwriter.png","language":"PHP","funding_links":["https://github.com/sponsors/ghostwriter"],"categories":[],"sub_categories":[],"readme":"# Config\n\n[![GitHub Sponsors](https://img.shields.io/github/sponsors/ghostwriter?label=Sponsor+@ghostwriter/config\u0026logo=GitHub+Sponsors)](https://github.com/sponsors/ghostwriter)\n[![Automation](https://github.com/ghostwriter/config/actions/workflows/automation.yml/badge.svg)](https://github.com/ghostwriter/config/actions/workflows/automation.yml)\n[![Supported PHP Version](https://badgen.net/packagist/php/ghostwriter/config?color=8892bf)](https://www.php.net/supported-versions)\n[![Downloads](https://badgen.net/packagist/dt/ghostwriter/config?color=blue)](https://packagist.org/packages/ghostwriter/config)\n\nProvides an object that maps configuration keys to values.\n\n## Installation\n\nYou can install the package via composer:\n\n``` bash\ncomposer require ghostwriter/config\n```\n\n### Star ⭐️ this repo if you find it useful\n\nYou can also star (🌟) this repo to find it easier later.\n\n## Features\n\n- 🔑 **Dot Notation**: Access nested configuration using dot, forward slash, or backslash separators\n- 🔄 **Flexible Merging**: Merge arrays, files, or directories\n- 🔧 **Array Operations**: Append and prepend values to configuration arrays\n- 🎯 **Scoped Configuration**: Wrap nested configuration into isolated instances\n\n## API\n\n```php\n/**\n * @template T of (array\u003cnon-empty-string,T\u003e|bool|float|int|null|string)\n */\ninterface ConfigurationInterface\n{\n    /** @throws ConfigurationExceptionInterface */\n    public function append(string $key, mixed $value): void;\n\n    /** @throws ConfigurationExceptionInterface */\n    public function get(string $key, mixed $default = null): mixed;\n\n    /** @throws ConfigurationExceptionInterface */\n    public function has(string $key): bool;\n\n    /**\n     * @param array\u003cnon-empty-string,T\u003e $options\n     * @throws ConfigurationExceptionInterface\n     */\n    public function merge(array $options): void;\n\n    /** @throws ConfigurationExceptionInterface */\n    public function mergeDirectory(string $directory): void;\n\n    /** @throws ConfigurationExceptionInterface */\n    public function mergeFile(string $file, ?string $key = null): void;\n\n    /** @throws ConfigurationExceptionInterface */\n    public function prepend(string $key, mixed $value): void;\n\n    public function reset(): void;\n\n    /** @throws ConfigurationExceptionInterface */\n    public function set(string $key, mixed $value): void;\n\n    /** @return array\u003cnon-empty-string,T\u003e */\n    public function toArray(): array;\n\n    /** @throws ConfigurationExceptionInterface */\n    public function unset(string $key): void;\n\n    /**\n     * @param array\u003cnon-empty-string,T\u003e $default\n     * @throws ConfigurationExceptionInterface\n     */\n    public function wrap(string $key, array $default = []): self;\n}\n```\n\n## Usage\n\nGiven the following configuration directory structure\n\n- `path/to/config/directory/app.php`\n- `path/to/config/directory/database.php`\n- `path/to/config/directory/file.php`\n\n```php\n$directory = 'path/to/config/directory';\n$file = 'path/to/config/directory/file.php';\n$options = [\n    'settings' =\u003e [\n        'enable' =\u003e true,\n    ],\n];\n\n$configuration = Configuration::new($options);\n$configuration-\u003ehas('settings.disabled'); // false\n$configuration-\u003eget('settings.disabled'); // null\n$configuration-\u003eget('settings.disabled', 'default'); // 'default'\n\n$configuration-\u003eset('settings.disabled', false);\n\n$configuration-\u003ehas('settings.disabled'); // true\n$configuration-\u003eget('settings.disabled'); // false\n\n$configuration-\u003etoArray(); // ['settings' =\u003e ['enable'=\u003etrue,'disabled'=\u003efalse]]\n\n$configuration-\u003eunset('settings.disabled');\n\n$configuration-\u003eget('settings.disabled'); // null\n$configuration-\u003eget('settings.disabled', 'default'); // 'default'\n\n$configuration-\u003etoArray(); // ['settings' =\u003e ['enable'=\u003etrue]]\n```\n\n```php\n// from an array\n$configuration = Configuration::new($options); \n$configuration-\u003etoArray(); // ['settings' =\u003e ['enable'=\u003etrue]]\n```\n\n```php\n// merge additional config options\n$additionalOptions = [\n    'settings' =\u003e [\n        'disabled' =\u003e false,\n    ],\n];\n$configuration = Configuration::new($options); \n$configuration-\u003emerge($additionalOptions);\n$configuration-\u003etoArray(); // ['settings' =\u003e ['enable'=\u003etrue,'disabled'=\u003efalse]]\n```\n\n```php\n// from an array with dot notation\n$configuration = Configuration::new($options); \n$configuration-\u003etoArray(); // ['settings' =\u003e ['enable'=\u003etrue]]\n\n$configuration-\u003ehas('settings'); // true\n$configuration-\u003ehas('settings.enable'); // true\n$configuration-\u003eget('settings.enable'); // true\n```\n\n```php\n// from a directory\n$configuration = Configuration::new();\n\n$configuration-\u003emergeDirectory($directory);\n\n$configuration-\u003etoArray(); // output below\n// [\n//      'app' =\u003e ['name'=\u003e'App','version'=\u003e'1.0.0'],\n//      'database' =\u003e ['host'=\u003e'localhost','port'=\u003e3306],\n//      'file' =\u003e ['path'=\u003e'/path/to/file']\n// ]\n```\n\n```php\n// from a file\n$configuration = Configuration::new();\n$configuration-\u003emergeFile($file);\n$configuration-\u003etoArray(); // ['path'=\u003e'/path/to/file']\n\n// from a file with a namespace key\n$configuration = Configuration::new();\n$configuration-\u003emergeFile($file, 'custom');\n$configuration-\u003etoArray(); // ['custom' =\u003e ['path'=\u003e'/path/to/file']]\n```\n\n```php\n// append values\n$configuration = Configuration::new($options); \n$configuration-\u003eappend('settings', ['key' =\u003e 'value']);\n$configuration-\u003etoArray(); // ['settings' =\u003e ['enable'=\u003etrue,'key'=\u003e'value']]\n```\n\n```php\n// prepend values\n$configuration = Configuration::new($options); \n$configuration-\u003eprepend('settings', ['key' =\u003e 'value']);\n$configuration-\u003etoArray(); // ['settings' =\u003e ['key'=\u003e'value','enable'=\u003etrue]]\n```\n\n```php\n// wrap configuration into a new scoped instance\n$configuration = Configuration::new([\n    'database' =\u003e [\n        'host' =\u003e 'localhost',\n        'port' =\u003e 3306,\n    ],\n]);\n\n$dbConfig = $configuration-\u003ewrap('database');\n$dbConfig-\u003eget('host'); // 'localhost'\n$dbConfig-\u003etoArray(); // ['host' =\u003e 'localhost', 'port' =\u003e 3306]\n\n// wrap with default values when key doesn't exist\n$cacheConfig = $configuration-\u003ewrap('cache', ['driver' =\u003e 'redis']);\n$cacheConfig-\u003etoArray(); // ['driver' =\u003e 'redis']\n```\n\n```php\n// reset configuration\n$configuration = Configuration::new(['key' =\u003e 'value']);\n$configuration-\u003etoArray(); // ['key' =\u003e 'value']\n\n$configuration-\u003ereset();\n$configuration-\u003etoArray(); // []\n```\n\n```php\n// mixed separators support (dot, forward slash, backslash)\n$configuration = Configuration::new();\n$configuration-\u003eset('app.name', 'MyApp');\n$configuration-\u003eget('app.name'); // 'MyApp'\n$configuration-\u003eget('app/name'); // 'MyApp' (forward slash)\n$configuration-\u003eget('app\\name'); // 'MyApp' (backslash)\n\n$configuration-\u003ehas('app.name'); // true\n$configuration-\u003ehas('app/name'); // true\n$configuration-\u003ehas('app\\name'); // true\n```\n\n```php\n// append/prepend to nested keys\n$configuration = Configuration::new();\n$configuration-\u003eappend('list.items', 'first');\n$configuration-\u003eappend('list.items', 'second');\n$configuration-\u003etoArray(); // ['list' =\u003e ['items' =\u003e ['first', 'second']]]\n\n$configuration-\u003eprepend('list.items', 'zero');\n$configuration-\u003etoArray(); // ['list' =\u003e ['items' =\u003e ['zero', 'first', 'second']]]\n```\n\n```php\n// automatic array promotion\n$configuration = Configuration::new();\n$configuration-\u003eset('parent', 'scalar');\n$configuration-\u003eset('parent.child', 'value'); // 'parent' is promoted to array\n$configuration-\u003etoArray(); // ['parent' =\u003e ['child' =\u003e 'value']]\n```\n\n### Changelog\n\nPlease see [CHANGELOG.md](./CHANGELOG.md) for more information on what has changed recently.\n\n### Credits\n\n- [Nathanael Esayeas](https://github.com/ghostwriter)\n- [All Contributors](https://github.com/ghostwriter/config/contributors)\n\n### License\n\nPlease see [LICENSE](./LICENSE) for more information on the license that applies to this project.\n\n### Security\n\nPlease see [SECURITY.md](./SECURITY.md) for more information on security disclosure process.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fghostwriter%2Fconfig","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fghostwriter%2Fconfig","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fghostwriter%2Fconfig/lists"}