Search by

byjg / config

byjg

A very basic and minimalist PSR-11 implementation for config management and dependency injection.

Package info

github.com/byjg/php-config

pkg:composer/byjg/config

Statistics

Installs: 14 007

Dependents: 1

Suggesters: 0

Stars: 4

Open Issues: 0

6.1.0 2026-07-17 13:00 UTC

README

sidebar_key config
sidebar_category infrastructure
tags
php

Configuration and Dependency Injection

Configuration and dependency injection in one PSR-11 container, with environments that inherit from each other and autowiring only where you choose it.

Sponsor Build Status Opensource ByJG Install MCP Server GitHub source GitHub license GitHub release

Why

Every application has a dev, a test, a staging and a production configuration that are mostly the same. Copying the files means a change has to be made in four places, and the container that builds your services usually decides for you how much is wired by magic.

Config builds the environments as a hierarchy:

$dev     = new Environment('dev');
$test    = new Environment('test', [$dev]);                  // dev, plus what test changes
$base    = new Environment('base', [$dev], abstract: true);  // shared, never loaded directly
$prod    = new Environment('prod', [$base], final: true);    // nothing may inherit from prod
  • Write a value once. An environment inherits everything from its parents and only states what is different. abstract and final keep the hierarchy honest.
  • Explicit bindings, autowiring when you want it. DI::bind() declares a service and its decisions (implementation, singleton, constructor arguments); an Autowire::rule() resolves a whole namespace by type hints. You choose per namespace, trading convenience for a plain lookup.

Features

  • PSR-11 Compatible: Implements PSR-11 Container Interface for standardized dependency injection
  • Auto-Initialization: Automatically loads configuration from a bootstrap file with zero setup
  • Static Facade: Clean, Laravel-style static API for accessing configuration anywhere
  • Environment-Based Configuration: Easily switch between development, production, and custom environments
  • Multiple Configuration Formats: Support for both PHP arrays and .env files
  • Dependency Injection: Simple API for defining and resolving dependencies
  • Type Conversion: Built-in parsers for converting configuration values to specific types
  • Caching Support: Optional caching of configuration values for improved performance
  • Environment Inheritance: Environments can inherit from one another to reduce configuration duplication
  • Abstract & Final Environments: Design flexible environment hierarchies with constraints
  • Performance Optimizations: Configure caching modes for different use cases

Quick Start with Auto-Initialization

The fastest way to get started is using the auto-initialization feature:

<?php
// 1. Create config/ConfigBootstrap.php
use ByJG\Config\ConfigInitializeInterface;
use ByJG\Config\Definition;
use ByJG\Config\Environment;

return new class implements ConfigInitializeInterface {
    public function loadDefinition(?string $env = null): Definition {
        $dev = new Environment('dev');
        $prod = new Environment('prod', [$dev]);

        return (new Definition())
            ->addEnvironment($dev)
            ->addEnvironment($prod);
    }
};
<?php
// 2. Create your config file (config/config-dev.php)
return [
    'database' => [
        'host' => 'localhost',
        'port' => 3306
    ],
    'app_name' => 'My Application',
    'debug' => true
];
<?php
// 3. Use Config anywhere in your app - no initialization needed!
use ByJG\Config\Config;

$appName = Config::get('app_name'); // "My Application"
$dbHost = Config::get('database')['host']; // "localhost"

Traditional Example

You can also use the traditional approach without auto-initialization:

<?php
// 1. Create a config file (config/config-dev.php)
return [
    'database' => [
        'host' => 'localhost',
        'port' => 3306
    ],
    'app_name' => 'My Application',
    'debug' => true
];

// 2. Set up and load the configuration
use ByJG\Config\Definition;
use ByJG\Config\Environment;

// Define the environments
$dev = new Environment('dev');
$prod = new Environment('prod', [$dev]); // prod inherits from dev

// Create and build the definition
$definition = (new Definition())
    ->addEnvironment($dev)
    ->addEnvironment($prod);

// Build with the current environment (using APP_ENV environment variable)
$container = $definition->build();

// 3. Use the configuration values
$appName = $container->get('app_name'); // "My Application"
$dbHost = $container->get('database')['host']; // "localhost"

Dependency Injection Example

<?php
// 1. Define your classes
namespace MyApp;

class DatabaseService 
{
    private $host;
    private $port;
    
    public function __construct(array $database) 
    {
        $this->host = $database['host'];
        $this->port = $database['port'];
    }
}

class UserRepository 
{
    private $db;
    
    public function __construct(DatabaseService $db) 
    {
        $this->db = $db;
    }
}

// 2. Register them in your config file
use ByJG\Config\DependencyInjection as DI;
use ByJG\Config\Param;

return [
    'database' => [
        'host' => 'localhost',
        'port' => 3306
    ],
    
    // Register the database service. A Param refers to the whole entry, so it receives the array
    \MyApp\DatabaseService::class => DI::bind(\MyApp\DatabaseService::class)
        ->withConstructorArgs([Param::get('database')])
        ->toSingleton(),
    
    // Register the repository with auto-injection
    \MyApp\UserRepository::class => DI::bind(\MyApp\UserRepository::class)
        ->withInjectedConstructor()
        ->toInstance(),

    // For mixed injection (auto-inject classes, manually provide scalars)
    \MyApp\UserService::class => DI::bind(\MyApp\UserService::class)
        ->withInjectedConstructorOverrides([
            'apiKey' => 'my-secret-key'  // Manually provide scalar values
        ])
        ->toInstance()
];

// 3. Use the services from the container
$userRepo = $container->get(\MyApp\UserRepository::class);

Documentation

Start with the fundamentals and move toward the advanced features following this order:

Installation

composer require "byjg/config"

Running Tests

./vendor/bin/phpunit

Open source ByJG