PHPackages                             jasny/container - 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. [PSR &amp; Standards](/categories/psr-standards)
4. /
5. jasny/container

Abandoned → [php-di/php-di](/?search=php-di%2Fphp-di)ArchivedLibrary[PSR &amp; Standards](/categories/psr-standards)

jasny/container
===============

Simple dependency injection container with autowire support

v2.1.2(6y ago)43.9k↓83.3%MITPHPPHP &gt;=7.2.0

Since Aug 27Pushed 6y agoCompare

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

READMEChangelog (4)Dependencies (5)Versions (10)Used By (0)

Jasny Container
===============

[](#jasny-container)

[![Build Status](https://camo.githubusercontent.com/ae947794559900baa21c7f30a5152def300085fcc4441607dabbc777e13a3c48/68747470733a2f2f7472617669732d63692e6f72672f6a61736e792f636f6e7461696e65722e7376673f6272616e63683d6d6173746572)](https://travis-ci.org/jasny/container)[![Code Coverage](https://camo.githubusercontent.com/bdc041f0c877724ce8bba31a7bd38f02ec422471aafb5fd24f4ebac84bfef03f/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f6a61736e792f636f6e7461696e65722f6261646765732f636f7665726167652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/jasny/container/?branch=master)[![Scrutinizer Code Quality](https://camo.githubusercontent.com/c1d5720602775cd64964c2e9dc8566220931af1ed24076f18a66c5d361ae27d7/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f6a61736e792f636f6e7461696e65722f6261646765732f7175616c6974792d73636f72652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/jasny/container/?branch=master)[![Packagist Stable Version](https://camo.githubusercontent.com/ef0f4eabfbe532a4db96ceee3db89d0fa66591c87da42f85f22d7520a7178f86/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6a61736e792f636f6e7461696e65722e737667)](https://packagist.org/packages/jasny/container)[![Packagist License](https://camo.githubusercontent.com/a90b9241c3064d237efe0b7bb0b80f991fa120676e8e7c592cb3ce53323f53a5/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f6a61736e792f636f6e7461696e65722e737667)](https://packagist.org/packages/jasny/container)

This package contains a simple dependency injection container compatible with [PSR-11](https://github.com/php-fig/fig-standards/blob/master/proposed/container.md).

The container supports (explicit) [**autowiring**](#autowiring) and [**subcontainers**](#subcontainers). `Container` objects are immutable.

Containers are used to help with [dependency injection](https://en.wikipedia.org/wiki/Dependency_injection), creating loosly coupled applications. DI helps in making making your application better testable and maintainable.

The following type of entries are typically added to the container;

- **Services** are objects of for which there is typically only one instance that is available throughout the application. Here DI replaces the use of global objects, singletons and service locators.
- [**Abstract factories**](https://sourcemaking.com/design_patterns/abstract_factory) are services specific for creating new instances. Use factories instead of using `new` in your classes. The factory allows mocking objects or using a different/customized implementation of the class.
- [**Prototype objects**](https://sourcemaking.com/design_patterns/prototype) is an alternative to using factories, where the prototype object is immutable. The object will be clones when used.
- **Configuration values** can be directly returned by the container, this is preferable to using a global configuration array, global constants or getting environment variables directly.

*Pro tip:* It's sometimes harder to get a dependency to a (deeply nested) object. In this case you might be tempted to resort to using the global scope via a Service Locator, Facade or Singleton. **Do not do this!** It will make your code much harder to test, maintain and reuse. Instead resolve the nesting by creating an abstract factory for the nested object and inject the service into the factory.

*This library is based on [Picontainer](https://github.com/thecodingmachine/picotainer).*

Installation
------------

[](#installation)

The Jasny Container package is available on [packagist](https://packagist.org/packages/jasny/meta). Install it using composer:

```
composer require jasny/container

```

The packages adheres to the [SemVer](http://semver.org/) specification, and there will be full backward compatibility between minor versions.

Declaring entries in the container
----------------------------------

[](#declaring-entries-in-the-container)

Creating a container is a matter of creating a `Container` instance passing the list of entries, as an **array of anonymous functions**.

```
use Jasny\Container\Container;
use Psr\Container\ContainerInterface;

$container = new Container([
    Foo::class => static function() {
        return new Foo();
    },
    BarInterface::class => static function(ContainerInterface $container) {
        $foo = $container->get(Foo::class);
        return new Bar($foo);
    },
    "bar" => static function(ContainerInterface $container) {
        return $container->get('bar'); // Alias for BarInterface
    },
    "APPLICATION_ENV" => static function(ContainerInterface $container) {
        return getenv('APPLICATION_ENV');
    }
]);
```

The list of entries is an associative array. The order of entries doesn't matter.

- The key is the name of the entry in the container.
- The value is an **anonymous function** (Closure) that will return the entry.

The entry can be anything (an object, a scalar value, a resource, etc...) The anonymous function must accept one parameter: the container on which dependencies will be fetched.

Any `iterable` may be passed to the container, not just plain arrays. Once the container has been created it's **immutable** entries can't be added, removed or replaced.

### Delegated lookup

[](#delegated-lookup)

If a delegate-lookup container was passed as the second argument of the constructor, it will be passed to the anonymous function instead.

```
$otherContainer = new Container([
    ZooInterface::class => static function(ContainerInterface $container) {
        $foo = $container->get(Foo::class); // $container is the $rootContainer
        return new Zoo($foo);
    }
}, $rootContainer);
```

### Entry loader

[](#entry-loader)

The `EntryLoader` can be used to load entries from PHP files in a directory. This is useful for larger applications to organize service declarations.

```
use Jasny\Container\Container;
use Jasny\Container\Loader\EntryLoader;

$files = new \GlobIterator(
    'path/to/declarations/*.php',
     \GlobIterator::CURRENT_AS_PATHNAME | \GlobIterator::SKIP_DOTS
);

$loader = new EntryLoader($files);
$container = new Container($loader);
```

The `EntryLoader` takes an Iterator. This can be an simple `ArrayIterator`, but more typically a `GlobIterator` or a `RecursiveDirectoryIterator`. See [SPL Iterators](http://php.net/manual/en/spl.iterators.php).

#### Class loader

[](#class-loader)

The `ClassLoader` is an alternative to the entry loader, to create entries based on a list of classes. The loader takes an `Iterator` with fully qualified classnames (FQCNs).

```
use Jasny\Container\Container;
use Jasny\Container\ClassLoader;

$loader = new ClassLoader(new \ArrayIterator(['App\Foo', 'App\Bar', 'App\Qux']));
$container = new Container($loader);
```

By default the entry key is the class name and autowiring is used to instantiate the service.

#### Custom instantiation

[](#custom-instantiation)

The second (optional) argument is a callback that is applied to each class to create the container entries. This function must return an array of Closures.

```
use Jasny\Container\Container;
use Jasny\Container\ClassLoader;
use Psr\Container\ContainerInterface;

$callback = static function(string $class): array {
    $baseClass = preg_replace('/^.+\\/', '', $class); // Remove namespace
    $id = strtolower($baseClass);

    return [
        $id => static function(ContainerInterface $container) use ($class) {
            $colors = $container->get('colors');
            return new $class($colors);
        }
    ];
};

$loader = new ClassLoader(new \ArrayIterator(['App\Foo', 'App\Bar', 'App\Qux']), $callback);
$container = new Container($loader);
```

#### Load all files in a folder

[](#load-all-files-in-a-folder)

Instead of just supplying a list of classes, you might want to scan a folder and add all the classes from that folder. This can be done with `FQCNIterator` from [jasny/fqcn-reader](https://github.com/jasny/fqcn-reader).

```
use Jasny\Container\Container;
use Jasny\Container\Loader\ClassLoader;
use Jasny\FQCN\FQCNIterator;

$directoryIterator = new \RecursiveDirectoryIterator('path/to/project/services');
$recursiveIterator = new \RecursiveIteratorIterator($directoryIterator);
$sourceIterator = new \RegexIterator($recursiveIterator, '/^.+\.php$/i', \RegexIterator::GET_MATCH);

$fqcnIterator = new FQCNIterator($sourceIterator);

$loader = new ClassLoader($fqcnIterator);
$container = new Container($loader);
```

This can also be combined with a callback.

### Modified copy

[](#modified-copy)

The container is immutable. It isn't possible to add or change entries after it has been created. However it is possible to get a copy of the container with modified entries using the `with()` method.

```
$testContainer = $container->with([
    Foo::class => static function() {
        return new DummyFoo();
    },
]);
```

The `with()` methods accepts an iterable with callbacks, similar to the container constructor. This means that loaders may be used to load replacement entries.

Fetching entries from the container
-----------------------------------

[](#fetching-entries-from-the-container)

Fetching entries from the container is done using the `get()` method:

```
$bar = $container->get(BarInterface::class);
```

Calls to the `get` method should only return an entry if the entry is part of the container. If the entry is not part of the container, a `Jasny\Container\NotFoundException` is thrown.

### Type checking

[](#type-checking)

If the entry identifier is an interface or class name, a `TypeError` is thrown if the entry doesn't implement the interface or extend the class.

Any identifier that starts with a capital and doesn't contain a `.` is seen a potential interface or class name, this is checked with `class_exists`.

```
// No type checking is done
$container->get('foo');
$container->get('datetime');
$container->get('My.thing');

// No checking is done because class doesn't exist
$container->get('FooBar');

// Checking is done
$container->get('Psr\Http\Message\ServerRequestInterface');
```

It's recommended to keep non-class/interface identifiers lowercase.

### Subcontainers

[](#subcontainers)

Entries of the container may also be a container themselves. In this case, you can use the `entry.subentry` to get an entry from the subcontainer. The subcontainer needs to implement `Psr\Container\ContainerInterface`, it doesn't need to be a `Jasny\Container` object.

```
use Jasny\Container;
use Psr\Container\ContainerInterface;

$container = new Container([
    'config' => static function(ContainerInterface $container) {
        return new Container([
            'secret' => static function() {
                return getenv('APPLICATION_SECRET');
            }
        ]);
    }
]);

$secret = $container->get('config.secret');
```

If the container contains a `config.secret` entry, the `config` container is not consulted. A multiple levels are used like `config.db.settings.host`, the container tries finding the an entry in the following order; `config.db.settings.host`, `config.db.settings`, `config.db`, `config`.

### Checking entries

[](#checking-entries)

To check if the container has an entry you can use the `has` method. It return `true` if the entry is part of the container and `false` otherwise.

#### Null object

[](#null-object)

*Pro tip:* Rather than using the `has` method, create a [Null object](https://sourcemaking.com/design_patterns/null_object). A null object correctly implements an interface, but does nothing. For example a `NoCache` object that doesn't actually cache values. Removing the `if` statements reduces complexity. The function calls are typically not more expensive than the if statement, so it doesn't hurt performance.

Autowiring
----------

[](#autowiring)

The container can be used to instantiate an object (instead of using `new`), automatically determining the dependencies. This can be handy when you find yourself constantly modifying specific entries.

To use autowiring, add a `Jasny\Autowire\AutowireInterface` entry to the container.

```
use Jasny\Container\Container;
use Jasny\Container\AutowireContainerInterface;
use Jasny\Autowire\AutowireInterface;
use Jasny\Autowire\ReflectionAutowire;
use Psr\Container\ContainerInterface;

$container = new Container([
    AutowireInterface::class => static function(ContainerInterface $container) {
        return new ReflectionAutowire($container);
    },
    Foo::class => static function(ContainerInterface $container) {
        return new Foo();
    },
    BarInterface::class => static function(AutowireContainerInterface $container) {
        return $container->autowire(Bar::class);
    }
]);
```

The `Container` class implements `AutowireContainerInterface` which defines an `autowire` method. The first argument is the class name.

Additional arguments may be provided, which are passed directly to the constructor. No autowiring is applied to these parameters.

**For more information see [jasny/autowire](https://github.com/jasny/autowire).**

*Pro tip:* Autowiring increases coupling, so use it sparsely.

Notes for the reader
--------------------

[](#notes-for-the-reader)

If you're using the PHPStorm IDE, install the [dynamic return type plugin](https://plugins.jetbrains.com/plugin/7251-dynamicreturntypeplugin) to get the correct type hint when doing `$container->get(SomeInterface::class)`.

###  Health Score

32

—

LowBetter than 72% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity23

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity63

Established project with proven stability

 Bus Factor1

Top contributor holds 62.3% 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 ~75 days

Recently: every ~132 days

Total

9

Last Release

2221d ago

Major Versions

v1.2.1 → v2.0.02019-09-06

PHP version history (2 changes)v1.0.0PHP &gt;=7.1.0

v2.0.0PHP &gt;=7.2.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/3379a93d51305df325df9045e1a8b205d195e4e8c01312dff53a000ee79002eb?d=identicon)[jasny](/maintainers/jasny)

---

Top Contributors

[![jasny](https://avatars.githubusercontent.com/u/100821?v=4)](https://github.com/jasny "jasny (38 commits)")[![moufmouf](https://avatars.githubusercontent.com/u/1290952?v=4)](https://github.com/moufmouf "moufmouf (18 commits)")[![Rayne](https://avatars.githubusercontent.com/u/1098733?v=4)](https://github.com/Rayne "Rayne (2 commits)")[![Sam-Burns](https://avatars.githubusercontent.com/u/6594039?v=4)](https://github.com/Sam-Burns "Sam-Burns (2 commits)")[![xhuberty](https://avatars.githubusercontent.com/u/8350192?v=4)](https://github.com/xhuberty "xhuberty (1 commits)")

---

Tags

containerPSR-11dependency-injection

### Embed Badge

![Health badge](/badges/jasny-container/health.svg)

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

###  Alternatives

[php-di/php-di

The dependency injection container for humans

2.8k48.9M994](/packages/php-di-php-di)[slince/di

A flexible dependency injection container

20260.4k6](/packages/slince-di)[phpwatch/simple-container

A fast and minimal PSR-11 compatible Dependency Injection Container with array-syntax and without auto-wiring

1810.1k2](/packages/phpwatch-simple-container)

PHPackages © 2026

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