PHPackages                             mathiasgrimm/di-container-php - 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. mathiasgrimm/di-container-php

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

mathiasgrimm/di-container-php
=============================

IoC Container with automatic dependency injection

06PHP

Since Feb 23Pushed 8y ago1 watchersCompare

[ Source](https://github.com/mathiasgrimm/di-container-php)[ Packagist](https://packagist.org/packages/mathiasgrimm/di-container-php)[ RSS](/packages/mathiasgrimm-di-container-php/feed)WikiDiscussions master Synced 2mo ago

READMEChangelogDependenciesVersions (1)Used By (0)

mathiasgrimm/di-container-php
=============================

[](#mathiasgrimmdi-container-php)

[![Build Status](https://camo.githubusercontent.com/09ebcafd1386821e252ae5668c2c8c1b0b4655974b2f7b66f47d999ff2c471e4/68747470733a2f2f7472617669732d63692e6f72672f6d6174686961736772696d6d2f64692d636f6e7461696e65722d7068702e737667)](https://travis-ci.org/mathiasgrimm/di-container-php?branch=master)[![Coverage Status](https://camo.githubusercontent.com/56aec21c88b6a3f192f27ac72d03b2b90dc8644729ca28ee5ea70ee443f71056/68747470733a2f2f636f766572616c6c732e696f2f7265706f732f6769746875622f6d6174686961736772696d6d2f64692d636f6e7461696e65722d7068702f62616467652e737667)](https://coveralls.io/github/mathiasgrimm/di-container-php)

Simple yet effective IoC Container with automatic dependency resolution

Basic Usage
-----------

[](#basic-usage)

### Singleton

[](#singleton)

When using singleton, the `Container->get()` method will always return the same object reference as it will be stored internally within the container.

```
$container = new Container();
$container->bindSingleton(SomeComponentInterface::class, function (Container $c, $params = []) {
    return new SomeComponentImplementation();
});

$aComponent = $container->get(SomeComponentInterface::class);

```

you can also bind non-objects, with arbitrary keys

```
$container = new Container();
$container->bindSingleton('db.credentials', [
    'user'     => getenv('db.username'),
    'password' => getenv('db.password')
]);

$dbCredentials = $container->get('db.credentials');

// OR
$container->bindSingleton('some-key', 'some-value');
$container->get('some-key');

```

### Factory

[](#factory)

When using a factory binding, the `Container->get()` will always return a new instance of what was bound. the `bindFactory` expects a callable (closure, or a class that implements the \_\_invoke magic method)

```
$container = new Container();
$container->bindFactory(SomeComponentInterface::class, function (Container $c, $params = []) {
    return new SomeComponentImplementation();
});

$aComponent = $container->get(SomeComponentInterface::class);

```

### Instance

[](#instance)

When using an instance binding it behaves the same as the singleton binding except it accepts only instances

```
$anObject  = new SomeObject();
$container = new Container();
$container->bindInstance(SomeInterface::class, $anObject);

$anObjectInstance = $container->get(SomeInterface::class);
echo $anObjectInstance === $anObject; // will always be true

// OR
$container->bindInstance('some-object', $anObject);
$anObjectInstance = $container->get('some-object');
echo $anObjectInstance === $anObject; // will always be true

```

### Extends

[](#extends)

Extends will replace the original value with the new value and will pass the old value via param. This way you could decorate your component.

The new binding will be of the same type. So if it was a factory it will still be a factory, if singleton it will still be a singleton and so on. For this reason, you cannot extend a component that hasn't been defined. If you try to do so you will get an ComponentNotRegisteredException exception

```

$container->bindSingleton(SomeInterface::class, function (Container $container, $params = []) {
    return new FileLogger();
});

$container->extend(SomeInterface::class, function (Container $container, $oldValue) {
    // oldValue is FileLogger
    $logger = new DecoratorLogger($oldValue);
    return $logger;
});

```

### General Rules for all bindings

[](#general-rules-for-all-bindings)

- you cannot bind a component that has been already used
- you cannot unbind a component that has been already user
- you cannot extend a component that has never been defined
- you cannot extend a component that has been already used

Usage with Container Providers
------------------------------

[](#usage-with-container-providers)

To centralise and/or make the bindings of your application more organised, you can use container providers. To use them you need to register them in the container. Every Container Provider has to implement the `ContainerProviderInterface`

```
class MyContainerProvider implements ContainerProviderInterface
{
    public function register(Container $container)
    {
        $container->bindSingleton(MailerInterface::class, function (Container $container, $params) {
            return new LocalMailer();
        });
    }

    public function boot(Container $container)
    {

    }
}

$container->register(new MyContainerProvider());

```

Therefore you application can have multiple container providers and it helps extending your application especially because third party vendors can provide some providers

#### The `register` method

[](#the-register-method)

This is where you can register your bindings and possibly not do anything else. If you try to have other functionalities in this method it could be that another container provider is not yet registered.

#### The `boot` method

[](#the-boot-method)

This is called only when all container providers have been registered and is safe to have some logic here as at this point container providers are loaded

#### Please see a more complete example bellow

[](#please-see-a-more-complete-example-bellow)

```
class MyContainerProvider implements ContainerProviderInterface
{
    public function register(Container $container)
    {
        $container->bindSingleton(MailerInterface::class, function (Container $container, $params) {
            return new LocalMailer();
        });
    }

    public function boot(Container $container)
    {

    }
}

interface MailerInterface
{
    public function send(Mail $mail);
}

class LocalMailer implements MailerInterface
{
    public function send(Mail $mail)
    {
        file_put_contents('somefolder/mailer.log');
    }
}

class MyController
{
    protected $mailer;

    public function __construct(MailerInterface $mailer)
    {
        $this->mailer = $mailer; // this will be the LocalMailer instance
    }

    public function emailUser($userId)
    {
        // ...
        $mail = new Mail();
        $mail->setTo($user->getEmail());
        // ...
        $this->mailer->send($mail);
    }
}

class HttpHandler
{
    protected $container;

    public function __construct(Container $container)
    {
        $this->container = $container;
    }

    public function handle()
    {
        // gets controllerName, method and params based on the route
        // $controllerName = MyController::class;
        // $mthod          = emailUser
        // $params         = ['user' => 1];

        $controller = $this->container->get($controllerName);

        $response = call_user_func_array([$controller, $method], $params);
        // same as $controller->emailUser(1);
    }
}

```

#### boot method

[](#boot-method)

The container `boot` method has to be called by your application so that all container providers will be booted

```
$container = new Container();
// $container->register(...);
// $container->register(...);
// $container->register(...);
$container->boot();

```

This does nothing more than loop through all registered container providers and call the `boot` on each one

### Definition Order

[](#definition-order)

It should not matter in which order you define your bindings as they are deferred until the moment they are needed.

For Example:

```
$container->bindSingleton(SomeInterfaceA::class, function (Container $c, $params = []) {
    $b = $container->get(SomeInterfaceB::class);
    $a = new SomeImplA($b);
    return $a;
});

$container->bindSingleton(SomeInterfaceB::class, function (Container $c, $params = []) {
    return new SomeImplB();
});

$container->get(SomeInterfaceA::class);

```

Even thought `SomeInterfaceA::class` depends on `SomeInterfaceB::class` and `SomeInterfaceB::class`was defined after `SomeInterfaceA::class` it will work just fine

Utility Methods
---------------

[](#utility-methods)

### get()

[](#get)

Get will try to return an instance/value even if the Interface/Class was not defined. It will do so by using reflection. It will also use a mixed approach, meaning, if parts of the dependency graph are registered, it will use it, otherwise it will try to dynamically load it.

```
class SomeComponent
{

}

$container->get(SomeComponent::class); // will return a SomeComponent instance.

```

When the object is dynamically loaded it will be always a singleton

Concrete dependencies can be resolved automatically

```
class A {}
class B {}

class SomeComponent
{
    public function __construct(A $a, B $b)
    {

    }
}

$container->get(SomeComponent::class); // will return a SomeComponent instance and provide the dependencies
automatically

```

if the request class/interface does not exist a `NotResolvedDependencyException` exception will be thrown

#### Limitations

[](#limitations)

When defining a class dependency, only classes and interfaces can be used. Scalar types will result in a `ParameterNotInstantiable` exception

### has()

[](#has)

Has checks whether there is a binding registered for a given key

```
$container->has(SomeInterface::class); // returns true or false

```

If has returns `false` it does not mean a `get(SomeInterface::class)` will throw an exception as it could still be loaded dynamically

### loaded()

[](#loaded)

Checks whether a key is loaded into the container, that would happen after you issue a get for a singleton or instance binding

```
$container->bindSingleton('some-key', 'some-key');
$container->loaded('some-key'); // return false
$container->get('some-key');
$container->loaded('some-key'); // returns true

```

For a factory binding it will always return false

If a key was never registered it will also return `false`

### unbind()

[](#unbind)

Unbind removes all internal references to a given key

Both `has` and `loaded` will return false to a key that has been `unbind()`

If a key does not exists it will not throw any exceptions

### frozen()

[](#frozen)

Checks whether a key is frozen on not.

#### frozen() vs. loaded()

[](#frozen-vs-loaded)

A key can be frozen and not be loaded. This is the case for factories

### booted()

[](#booted)

Whether the container has been already booted or not

Contextual Binding
------------------

[](#contextual-binding)

Every utility method, including the `get`, have a possibility to pass a context.

There are some cases where you have components that depend on the same interface but actually use two different implementations

```
$container->bindSingleton(LoggerInterface::class, function () {
    return new SlackLogger();
}, ControllerA::class);

$container->bindSingleton(LoggerInterface::class, function () {
    return new FileLogger();
}, ControllerB::class);

// you can explicitly inform the context to get the loggers
$container->get(LoggerInterface::class, [], ControllerA::class); // will return SlackLogger
$container->get(LoggerInterface::class, [], ControllerB::class); // will return FileLogger

// and you can also call the controller classes and the dependencies will be injected as you need
$container->get(ControllerA::class);
$container->get(ControllerB::class);

// ------------------------------------------------------
// controllers
// ------------------------------------------------------
class ControllerA
{
    public function __construct(LoggerInterface $logger)
    {
        // logger will be the SlackLogger
    }
}

class ControllerB
{
    public function __construct(LoggerInterface $logger)
    {
        // logger will be the FileLogger
    }
}

```

Using Contextual binding and default binding

```
// default context
$container->bindSingleton(LoggerInterface::class, function () {
    return new SlackLogger();
});

// ControllerB context
$container->bindSingleton(LoggerInterface::class, function () {
    return new FileLogger();
}, ControllerB::class);

$container->get(ControllerA::class);
$container->get(ControllerB::class);

class ControllerA
{
    public function __construct(LoggerInterface $logger)
    {
        // logger will be the SlackLogger
    }
}

class ControllerB
{
    public function __construct(LoggerInterface $logger)
    {
        // logger will be the FileLogger
    }
}

```

Contextual binding is a way to define: when loading this class, please provide this implementation.

###  Health Score

20

—

LowBetter than 14% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity4

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity41

Maturing project, gaining track record

 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.

### Community

Maintainers

![](https://www.gravatar.com/avatar/56f4dbd80bb6510bdc2adc49fcf7ec925cb45535b3bfdadf0964a09d678cf8ab?d=identicon)[mathiasgrimm](/maintainers/mathiasgrimm)

---

Top Contributors

[![mathiasgrimm](https://avatars.githubusercontent.com/u/450069?v=4)](https://github.com/mathiasgrimm "mathiasgrimm (26 commits)")

### Embed Badge

![Health badge](/badges/mathiasgrimm-di-container-php/health.svg)

```
[![Health](https://phpackages.com/badges/mathiasgrimm-di-container-php/health.svg)](https://phpackages.com/packages/mathiasgrimm-di-container-php)
```

###  Alternatives

[josh-taylor/sage-svg

WordPress package to enable a blade directive to use SVG images inline with Sage 9

1846.3k](/packages/josh-taylor-sage-svg)

PHPackages © 2026

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