PHPackages                             mattferris/di - 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. mattferris/di

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

mattferris/di
=============

A dependency injection library for PHP

1.0(6y ago)1388[1 issues](https://github.com/mattferris/di/issues)3BSD-2-ClausePHPCI failing

Since May 4Pushed 3y ago1 watchersCompare

[ Source](https://github.com/mattferris/di)[ Packagist](https://packagist.org/packages/mattferris/di)[ RSS](/packages/mattferris-di/feed)WikiDiscussions master Synced 1w ago

READMEChangelog (2)Dependencies (3)Versions (8)Used By (3)

DI
==

[](#di)

[![Build Status](https://camo.githubusercontent.com/03e4c361903b30972e6b61ad6358dc148cabb423a5fcd7af0e9c7371e0ef4ef5/68747470733a2f2f7472617669732d63692e6f72672f6d6174746665727269732f64692e7376673f6272616e63683d6d6173746572)](https://travis-ci.org/mattferris/di)[![SensioLabsInsight](https://camo.githubusercontent.com/0a9dd04b4608b34dcf9c86bcf56996cf72e584a56de96b02c9562293169a654d/68747470733a2f2f696e73696768742e73656e73696f6c6162732e636f6d2f70726f6a656374732f61383863313136612d333031392d343537332d386661312d3062383434646461323264642f6d696e692e706e67)](https://insight.sensiolabs.com/projects/a88c116a-3019-4573-8fa1-0b844dda22dd)

DI is a dependency injection container library for PHP.

Registering Services
--------------------

[](#registering-services)

To start out, create an instance of `MattFerris\Di\Di`. Use the `set()` method to register services, passing an instance of the service, or use a Closure are used to return an instance of the service and accomplish any appropriate intialization. You can get an instance of the container by specifying an argument named `$di`, or by specyfing any argument with a type-hint of `MattFerris\Di\Di` or `MattFerris\Di\ContainerInterface`.

```
use MattFerris\Di\Di;

$di = new Di();

// register 'FooService'
$di->set('FooService', return new \FooService());
});

// register `BarService` using type-hinted argument
$di->set('FooService', function (Di $container) {
    return new \FooService($container);
});
```

An instance of the service can now be retrieved via `get()`.

```
$fooService = $di->get('FooService');
```

Each request for the service will return the same instance of `FooService`. By default, all definitions are singletons. A third argument can be used to disable this behaviour.

```
$di->set('FooService', function ($di) {
    return new \FooService();
}, Di::NON_SINGLETON);
```

Now every call to `$di->get('FooService')` will return a new instance of `\FooService()`;

If your service relies on another service, a reference to the other service can easily be retrieved from within the definition either by manually retrieving it from the container or by having it injected.

```
// manually retrieve an instance of FooService
$di->set('BarService', function ($di) {
    $fooService = $di->get('FooService');
    return new \BarService($fooService);
});

// inject an instance of FooService
$di->set('BarService', function (\FooService $fooService) {
    return new \BarService($fooService);
});
```

You can check if a service has been defined using `has()`.

```
if ($di->has('FooService')) {
    echo 'Yay!';
}
```

You can use `find()` to return all services matching a prefix. This is useful if you have multiple services of a similar type and their definitions are named similarly. For example, if you have two remote FTP servers and you wanted to save a file to both of them, you could register the FTP services as `FTP.host1' and `FTP.host2`. Using `find()` to pull instances of these services allows you application to remain host agnostic, allow you to seamlessly configure additional hosts in the future.

```
$services = $di->find('FTP.');

foreach ($services as $key => $service) {
    $service->saveFile($file);
}
```

`$services` would look like:

```
array(
    'FTP.host1' => [instance of \FtpService],
    'FTP.host2' => [instance of \FtpService]
)
```

If you attempt to set a definition using a key that already exists, a `DuplicateDefinitionException` will be throw. The duplicate key can be retrieved using the `DuplicateDefinitionException::getKey()` method.

### Type-Based Injection

[](#type-based-injection)

In some cases, you may require a specific type of object for your service definition, but may not know what the name of the service's definition is within the container. Instead of requesting the directly from the container, you can have the service injected into your the closure of your service definition by type-hinting the argument.

```
$di->set('FooService', function (\Bar\Service\Class $bar) {
    return new \FooService($bar);
});
```

If a definition exists that has an instance of `\Bar\Service\Class`, it will injected into the closure for consumption by your defined service. Likewise, you could also specify an interface or a trait name to inject.

If a dependency can't be resolved, a `DependencyResolutionExceptioon` will be thrown. The type that couldn't be resolved can be retrieved using the `DependencyResolutionException::getType()` method.

Optionally, `Di` can use deep resolution of a dependency. This can be enabled by calling `$di->setDeepTypeResolution(true)`. When enabled, for type-based dependencies that can't be satisfied using definitions within the container, `Di` will attempt to instantiate an new instance of the type directly and use the new instance to satisfy the dependency. Constructor arguments will attempt to be satisfied using dependency injection as well.

### Service Providers

[](#service-providers)

You can use *providers* to isolate service configuration within your domains. A service *provider* is any class that extends `MattFerris\Di\ServiceProvider`, or implements `MattFerris\Provider\ProviderInterface`. When registered via `register($provider)`, the *provider's* `provides()` method is passed an instance of the container and can then register services.

```
class MyProvider extends MattFerris\Di\ServiceProvider
{
    public function provides($consumer)
    {
        // validate consumer is an instance of \MattFerris\Di\ContainerInterface
        parent::provides($consumer);

        $di->set('MyService', function () { ... });
    }
}

$di->register(new MyProvider());

$myService = $di->get('MyService');
```

Defining Parameters
-------------------

[](#defining-parameters)

You can define parameters for any service definitions to use via `setParameter()` and `getParameter()`. This allows you to create more dynamic service definitions and configurations.

```
$di->setParameter('db', array(
    'user' => 'joe',
    'pass' => 'p4ssw0rd',
    'host' => 'localhost',
    'db' => 'foo'
));

$di->set('DB', function ($di) {
    $cfg = $di->getParameter('db');
    return new \DbConnection(
        $cfg['user'], $cfg['pass'], $cfg['host'], $cfg['db']
    );
}, true);
```

The database connection settings can now be defined dynamically. Also notice the DB service is defined as a singleton.

Delegation
----------

[](#delegation)

Key prefixes can be delegated to other containers for lookup. This allows parts of your application, or third party components, to configure their own local containers, but plug them into a central container.

```
$di->delegate('Foo.', $container);
```

Now, any key beginning with `Foo.` will be delegated to `$container` for handling.

Custom Injection
----------------

[](#custom-injection)

In some cases, you may want to dynamically instantiate a class, or call a method (static or otherwise), closure or function. The methods `injectConstructor()`, `injectionMethod()`, `injectStaticMethod()`, and `injectFunction()` can accomplish this in a flexible way.

```
class FooClass
{
    public function __construct($argA, $argB)
    {
    }
}

$object = $di->injectConstructor(
    'FooClass',
     array('argA' => 'foo', 'argB' => 'bar')
);
```

The above example returns an instance of `FooClass` with injected constructor arguments. Take note that the second argument passed to `injectConstructor()`is an array, and this array defines which arguments get which values. These values can be specified in any order, and the method will match the keys with the actual argument names in the contructors signature. The following example would have the same result.

```
$object = $di->injectConstructor(
    'FooClass',
    array('blah' => 'bling', 'argB' => 'bar', 'argA' => 'foo')
);
```

`injectConstructor()` assigns the appropriate keys to their corresponding arguments. Keys with no corresponding argument are ignored. This principle is the same for the other `inject` methods.

```
$result = $di->injectMethod($object, 'someMethod', array('foo' => 'bar'));

$result = $di->injectStaticMethod('FooClass', 'someMethod', array('foo' => 'bar'));

$result = $di->injectFunction('someFunction', array('foo' => 'bar'));

$result = $di->injectFunction($closure, array('foo' => 'bar'));
```

Of course, you could inject defined services and parameters as well.

```
$object = $di->injectConstructor(
    'FooClass',
    array('argA' => $di->get('FooService'), 'argB' => $di->getParameter('foo'))
);
```

For convenience, the `inject` methods understand placeholders for services and parameters.

```
$object = $di->injectConstructor(
    'FooClass',
    array('argA' => '%FooService', 'argB' => ':foo')
);
```

Services can be referenced by prefixing the service name with a percent sign (%), and parameters can be referenced by prefixing the parameter name with a colon (:).

Type-based injection occurs in all cases when using the `inject*` methods unless the argument is supplied when invoking the method. In this way, you can override type-based injection for particular arguments. You can also force type-based injection on arguments by supplying a type for an argument.

```
$object = $di->injectConstructor(
    'FooClass',
    array('argA' => '\Foo\Service\Class')
);
```

Argument values starting with a backslash are assumed to be type-hinted arguments.

###  Health Score

26

—

LowBetter than 41% of packages

Maintenance0

Infrequent updates — may be unmaintained

Popularity14

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity68

Established project with proven stability

 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.

###  Release Activity

Cadence

Every ~434 days

Total

5

Last Release

2319d ago

Major Versions

0.4 → 1.02020-02-03

### Community

Maintainers

![](https://www.gravatar.com/avatar/9d3d46e7fdc93a3d67119773bdae779e281a87f2d70e95568a969c72205aedf7?d=identicon)[mattferris](/maintainers/mattferris)

---

Top Contributors

[![mattferris](https://avatars.githubusercontent.com/u/1687325?v=4)](https://github.com/mattferris "mattferris (25 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/mattferris-di/health.svg)

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

###  Alternatives

[symfony/dependency-injection

Allows you to standardize and centralize the way objects are constructed in your application

4.2k447.1M8.9k](/packages/symfony-dependency-injection)[illuminate/contracts

The Illuminate Contracts package.

706127.7M12.4k](/packages/illuminate-contracts)[illuminate/container

The Illuminate Container package.

31080.7M2.3k](/packages/illuminate-container)[symfony/type-info

Extracts PHP types information.

20062.9M225](/packages/symfony-type-info)[ecotone/ecotone

Enterprise architecture layer for Laravel and Symfony — CQRS, Event Sourcing, Durable Workflows (Sagas, Orchestrators), Projections, and Outbox messaging via PHP attributes.

562565.8k41](/packages/ecotone-ecotone)[civicrm/civicrm-core

Open source constituent relationship management for non-profits, NGOs and advocacy organizations.

744284.3k34](/packages/civicrm-civicrm-core)

PHPackages © 2026

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