Config: Container PSR-11 and Dependency Injection

Opensource ByJG Scrutinizer Code Quality Build Status

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

How it Works?

The container is created based on your current environment (dev, homolog, test, live, …) defined in array files;

See below how to setup:

Setup files:

Create in your project root at the same level of the vendor directory a folder called config.

Inside this folders create files called “config-dev.php”, “config-test.php” where dev, test, live, etc are your environments.

Your folder will look like to:

<project root>
    +-- config
           + config-dev.php
           + config-homolog.php
           + config-test.php
           + config-live.php
   +-- vendor
   +-- composer.json

Create environment variable

You need to setup a variable called “APPLICATION_ENV” before start your server.

This can be done using nginx:

fastcgi_param   APPLICATION_ENV  dev;





Docker CLI

docker -e APPLICATION_ENV=dev image

Configuration Files

The config-xxxx.php file



return [
    'property1' => 'string',
    'property2' => true,
    'property3' => function () {
        return 'xxxxxx';
    'propertyWithArgs' => function ($p1, $p2) {
        return 'xxxxxx';



return [
    'property2' => false

The xxxx.env file

Alternatively is possible to set an .env file with the contents KEY=VALUE one per line.



By default, all properties are parsed as string. You can parse as bool, int or float as this example:

PARAM1=!bool true
PARAM2=!int 20
PARAM3=!float 3.14

Use in your PHP Code

Create the Definition:

$definition = (new \ByJG\Config\Definition())
    ->environmentVar('APPLICATION_ENV') // This will setup the environment var to 'APPLICATION_ENV' (default)
    ->addEnvironment('homolog')         // This will setup the HOMOLOG environment
    ->addEnvironment('live')            // This will setup the LIVE environenment inherited HOMOLOG
    ->setCache($somePsr16Implementation, 'live'); // This will cache the result only to live Environment;

The code below will get a property from the defined environment:

$container = $definition->build();
$property = $container->get('property2');

If the property does not exists an error will be throwed.

If the property is a closure, you can call the get method and you’ll get the closure execution result:

$container = $definition->build();
$property = $container->get('closureProperty');
$property = $container->get('closurePropertyWithArgs', 'value1', 'value2');
$property = $container->get('closurePropertyWithArgs', ['value1', 'value2']);

If you want get the RAW value without parse clousure:

$container = $definition->build();
$property = $container->raw('closureProperty');

Dependency Injection


It is possible to create a Dependency Injection and set automatically the instances and constructors. Let’s get by example the following classes:

namespace Example;

interface Area
    public function calculate();

class Square implements Area
    public function __construct($side)
        // ...

class RectangleTriangle implements Area
    public function __construct($base, $height)
        // ...

We can create a definition for this classes:


use ByJG\Config\DependencyInjection as DI;

return [
    \Example\Square::class => DI::bind(\Example\Square::class)

    \Example\RectangleTriangle::class => DI::bind(\Example\RectangleTriangle::class)
        ->withConstructorArgs([3, 4])

and to use in our code we just need to do:

$config = $definition->build();
$square = $config->get(\Example\Square::class);

Injecting automaticatically the Objects

Let’s figure it out this class:

class SumAreas implements Area
     * SumAreas constructor.
     * @param \DIClasses\RectangleTriangle $triangle 
     * @param \DIClasses\Square $square 
    public function __construct($triangle, $square)
        $this->triangle = $triangle;
        $this->square = $square;


Note that this class needs instances of objects previously defined in our container definition. In that case we just need add this:

return [
    // ....

    SumAreas::class => DI::bind(SumAreas::class)

When use use the method withConstructor() we are expecting that all required classes in the constructor already where defined and inject automatically to get a instance.

This component uses the PHP Document to determine the classed are required.

Get a singleton object

The DependencyInjection class will return a new instance every time you require a new object. However, you can the same object by adding toSingleton() instead of toInstance().

All options:


    // To create a new instance choose *only* one below:
    ->withInjectedConstructor()         // If you want inject the constructor automatically using reflection
    ->withInjectedLegacyConstructor()   // If you want inject the constructor automatically using PHP annotation
    ->withNoConstrutor()                // The class has no constructor
    ->withConstructorArgs(array)        // The constructor's class arguments
    ->withFactoryMethod("method", array_of_args)  // When the class has a static method to instantiate instead of constructure 

    // Call methods after you have a instance
    ->withMethodCall("methodName", array_of_args)
    // How will you get a instance?
    ->toInstance()                   // get a new instance for every container get
    ->toSingleton()                  // get the same instance for every container get 
    ->toEagerSingleton()             // same as singleton however get a new instance immediately  

Checking current environment



composer require "byjg/config=4.0.*"