romchik38/php-container

PSR-11: Container interface

Installs: 1

Dependents: 0

Suggesters: 0

Security: 0

Stars: 1

Watchers: 1

Forks: 0

Open Issues: 0

pkg:composer/romchik38/php-container

2.0.4 2025-11-06 10:52 UTC

This package is auto-updated.

Last update: 2025-12-19 12:40:24 UTC


README

status status: ready to use phpstan phpstan: level 8 phpunit phpunit: full

The Container helps configure an application. The implementation is compatible with PSR-11 ContainerInterface.

Main features:

  • stores values as is (primitive, objects etc).
  • creates a shared object (singleton).
  • creates a fresh copy of the same class on each call.
  • multi ability to create a different instance of the same class by provided keys.
  • link a key to another key
  • promises - container creates an instance only on a get call, to avoid unused creations.
  • can detect a circular dependency
  • can be in lazy mode

Latest version

see changelog

Install

composer install romchik38/php-container

Quick examples

Primitive

Primitive class is responsible to hold a static mixed value. Use method add to store it.

$container = new \Romchik38\Container\Container();
$container->add('some key', 'any string');
$container->add('config', ['key' => 0]);
$container->add('important_object', new ImportantClass());
// somewhere in the code
$str = $container->get('some key');
// ...etc

Shared

Shared class is responsible to create only one instance of concrete class and returns it on each get request. Use method shared there.

$container = new \Romchik38\Container\Container();
$container->shared(
    '\Classes\Primitive1',                 // class name
    [7]                                    // params, number 7 in this case
);
// $shared1 and $shared2 are the same
$shared1 = $container->get('\Classes\Primitive1');
$shared2 = $container->get('\Classes\Primitive1');

Fresh

Fresh class is responsible to create a new instance of concrete class on each get request. Use method fresh of the container.

$container = new \Romchik38\Container\Container();
$container->fresh(
    '\Classes\Primitive1',                  // class name
    [7]                                     // params, number 7 in this case
);
// $fresh1 and $fresh2 are defferent objects that hold the same number 7
$fresh1 = $container->get('\Classes\Primitive1');
$fresh2 = $container->get('\Classes\Primitive1');

Multi

Multi class is responsible to create a new (or shared) copy of a concrete class with a given key. It maght be usefull when dealing with interfaces or creating a few same classes with different configuration. Use method multi.

// Interface example
$container = new \Romchik38\Container\Container();
$container->multi(
    '\DB\DatabaseUseSql',
    '\DatabaseInterface',
    true,                           // true - shared, false - fresh
    ['dsn:localhost']               // params
);

$database = $container->get('\DatabaseInterface');

Link

Link class helps to connect one key with another key. Use method link to store it. You can also make a reference to the class. This can be useful when using Interfaces.

$container = new \Romchik38\Container\Container();
$container->add('some key', 'any string');
$container->link('another key', 'some key');
// somewhere in the code
$str = $container->get('another key');
// $str holds 'any string'

Promises

Promise is responsible to defer a creation of the class's dependency. It used when a class has another class as a dependency.

Promises can be used with methods shared, fresh and multi.

$container = new \Romchik38\Container\Container();
$container->shared(
    '\DB\Database', 
    [
        'db:mysql',                         // first param as a string
        new Promise('\SomeConnection'),     // second param as a promise
    ]
);

In the example above, we promise to add a class \SomeConnection to the container. \SomeConnection is a class name, but it can be any key, used with multi method. In other words we pass a container key as a param.

Do not forget to add a \SomeConnection

$container->fresh(
    '\SomeConnection',     // class name
    []                     // params, in that case is nothing
);

Circular dependency detection

We can primise to add the first class to another, and a the second class to the first and so on. Promise chain can be as long as you want. But if you try to add a class as a promise which depends on any early promised classes an exception will be thrown.

$container = new \Romchik38\Container\Container();

$container->shared(
    '\ClassA1', 
    [new Promise('\ClassA2')]
);

$container->shared(
    '\ClassA2', 
    [new Promise('\ClassA1')]
);
// Exception there

Data Replacement

Currently, it is only possible to override data for Primitives that are added with the add method. An attempt to replace data using other methods will throws an error ContainerException.

$id        = 'key';
$container = new \Romchik38\Container\Container();
$container->add($id, 'value');
$container->add($id, 'value2');
$value = $container->get($id);  // value2

Lazy mode

$container = new \Romchik38\Container\Container(true);
$container->shared('\Classes\Primitive1', [7]);

// $shared1 is not initialized
$shared1 = $container->get('\Classes\Primitive1');

// $shared is initialized, because access on property numb which holds 7
$shared1->numb;

Code quality

  • phpstan level 8
    • passes[OK] No errors
  • phpunit
    • passesOK (40 tests, 59 assertions)
    • tested partially
  • laminas-coding-standard
    • passes34 / 34 (100%)

Projects that use this product

The PHP container was used to build the bootstrap system in the following projects:

  • Site1
  • Site2

Site1

Site1 is a simple website — that demonstrates a multi-page site with a login system, a sitemap, Google reCAPTCHA, and email-based password recovery. See source code on github page.

Also available Live Site1 preview.

Site2

Site2 is a more complex version of the site1 with more functionality. It demonstrates a multilanguage system, twig view, Image Converter and other features. See source code on github page.

Also available Live Site2 preview.