PHPackages                             prinsfrank/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. prinsfrank/container

ActiveLibrary[PSR &amp; Standards](/categories/psr-standards)

prinsfrank/container
====================

A strict PSR-11 implementation

v0.3.0(1y ago)42.1k↑75%MITPHPPHP ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0CI passing

Since Jul 7Pushed 1y ago1 watchersCompare

[ Source](https://github.com/PrinsFrank/container)[ Packagist](https://packagist.org/packages/prinsfrank/container)[ GitHub Sponsors](https://github.com/PrinsFrank)[ RSS](/packages/prinsfrank-container/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (6)Dependencies (6)Versions (8)Used By (0)

  ![Banner](https://github.com/PrinsFrank/container/raw/main/docs/images/banner_light.png)Container
=========

[](#container)

[![GitHub](https://camo.githubusercontent.com/1e2fad1acfadd555639ded1f6df8940d8985c821c23108775dc370b22e9a95f7/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f7072696e736672616e6b2f636f6e7461696e6572)](https://github.com/PrinsFrank/container/blob/main/LICENSE)[![PHP Version Support](https://camo.githubusercontent.com/f8b9ef05b16d86554d3f2560b888b399e20d9cd368a2d5f4f67a0fae195023bf/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f7072696e736672616e6b2f636f6e7461696e6572)](https://github.com/PrinsFrank/container/blob/main/composer.json)[![codecov](https://camo.githubusercontent.com/7b464edc3a9032b7860d8a41a235cf71fe58268c16662b6d581e2b5bdac1107f/68747470733a2f2f636f6465636f762e696f2f67682f5072696e734672616e6b2f636f6e7461696e65722f6272616e63682f6d61696e2f67726170682f62616467652e7376673f746f6b656e3d394f3356423536334d55)](https://codecov.io/gh/PrinsFrank/container)[![PHPStan Level](https://camo.githubusercontent.com/83dd3d35cebed0eab9ee97ff1a5849c1344cda6a8ee9cac2cda20f5aa55b67bd/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048505374616e2d6c6576656c253230392d627269676874677265656e2e7376673f7374796c653d666c6174)](https://github.com/PrinsFrank/container/blob/main/phpstan.neon)

**A strict container implementation**

Setup
-----

[](#setup)

> **Note**Make sure you are running PHP 8.1 or higher to use this package

To start right away, run the following command in your composer project;

`composer require prinsfrank/container`

Or for development only;

`composer require prinsfrank/container --dev`

Why this container package?
===========================

[](#why-this-container-package)

1. Dynamic Concrete Bindings
----------------------------

[](#1-dynamic-concrete-bindings)

At the entrypoints of an application - like controllers or commands - There might be instance where you'd want to inject a wide variety of different classes.

In most containers, If you'd want to automatically resolve [all requests for example](https://github.com/PrinsFrank/object-resolver), you'd have to register each individual concrete class in a service provider:

```
private const REQUEST_CLASSES = [
    // list of classes
];

public function provides(string $id): bool {
    return in_array($id, self::REQUEST_CLASSES, true);
}

public function register(mixed ...): void {
    foreach (self::REQUEST_CLASSES as $requestClass) {
        $this->container->add(
            $requestClass,
            fn() => $objectResolver->resolve($requestClass)
        )
    }
}
```

This means, that even if the provider was deferred and all requests were not added to the container at container initialization, as soon as one request gets requested and the service provider is booted, all requests will be registered. This increase the memory footprint, but also performs unnecessary actions, as most likely we will only ever use one request per execution cycle.

Instead, in this package, it is possible to add Dynamic Concrete Bindings. The identifier that was requested by the consumer is passed to the service provider. Not only to the `provides` method, but also to the `register` method:

```
final class RequestDataProvider implements ServiceProviderInterface {
    public function provides(string $identifier): bool {
        return is_a($identifier, RequestData::class, true);
    }

    public function register(string $identifier, DefinitionSet $resolvedSet): void {
        $resolvedSet->add(
            new Concrete(
                $identifier,
                fn (ObjectResolver $objectResolver) => $objectResolver->resolve($identifier),
            )
        );
    }
}
```

As you can see above, as long as there is an interface that is implemented by all the requests, it's now possible to resolve all requests without needing to manually keep a list of what request classes exist, and without the need to register tens, hundreds or even thousands of mostly unneeded classes in the container.

2. No opaque entry identifiers, only class-strings
--------------------------------------------------

[](#2-no-opaque-entry-identifiers-only-class-strings)

Unlike other containers, this package is fully strict with service entry identifiers. Instead of **any** string as an entry identifier, this package only allows FQNs of existing classes and interfaces. A simple `'db'` string to identify a `\DatabaseConnection` instance is therefore not allowed. This means that this package is very static-analysis friendly, as it's not necessary to boot the container in static analysis to determine the type of object that is located by an entry identifier.

This does slightly diverge from the PSR-11 standard, $1.1.1 Entry Identifiers, where the [following is specified](https://www.php-fig.org/psr/psr-11/#111-entry-identifiers):

> An entry identifier is any PHP-legal string of at least one character that uniquely identifies an item within a container. An entry identifier is an opaque string, so callers SHOULD NOT assume that the structure of the string carries any semantic meaning.

In the context of **this** container package, the following is true instead:

> An entry identifier is any class-string for a class or interface. Callers can assume that the returned object for an entry identifier that is a class-string of an interface implements that interface, a class-string of an abstract class results in an object that extends that abstract class and a class-string of a concrete class is an instance of that concrete class or a child thereof.

As most entry identifiers are already class-strings, this is not a big chance, but it makes things a lot more elegant. All other specification points from PSR-11 are still valid.

3. DI'ed services in ServiceProvider closure
--------------------------------------------

[](#3-died-services-in-serviceprovider-closure)

Let's assume we have a service (A) can only be partially resolved because it has two dependencies, one that can be resolved by the container (B) and one that cannot (C).

When autowiring is enabled, you could simply add a definition for the service that cannot be resolved (C) so that service A can also be resolved. But if the argument is not a service or should not be universally available, you can also request the services that are available as arguments for the service closure:

```
class FooApiServiceProvider implements ServiceProviderInterface {
    public function provides(string $identifier): bool {
        return $identifier === FooApi::class;
    }

    public function register(string $identifier, DefinitionSet $resolvedSet, Container $container): void {
        $resolvedSet->add(
            new AbstractConcrete(
                $identifier,
                static function (Environment $environment, ClientInterface $client) {
                    return new FooApi($environment->get('FOO_API_KEY'), $client)
                }
            )
        );
    }
}
```

Feature comparison with other containers
----------------------------------------

[](#feature-comparison-with-other-containers)

PrinsFrankLeaguePHP-DILaravel1No opaque entry identifiers✅❌❌❌Dynamic abstract concrete bindings✅❌❌❌No dependencies to other packages2✅✅❌❌DI'ed services in ServiceProvider Closures✅❌❌❌Autowiring✅✅✅✅1 Published as illuminate/container
2 Other than the psr/container interface

###  Health Score

35

—

LowBetter than 80% of packages

Maintenance45

Moderate activity, may be stable

Popularity24

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity52

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 96.8% 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 ~51 days

Total

6

Last Release

425d ago

PHP version history (3 changes)v0.1PHP ~8.3.0

v0.1.1PHP ~8.1.0 || ~8.2.0 || ~8.3.0

v0.2.0PHP ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/288919c24dc651727390578a2bfe6ef020f6f508c30db717b54c943a9e2ac0b3?d=identicon)[PrinsFrank](/maintainers/PrinsFrank)

---

Top Contributors

[![PrinsFrank](https://avatars.githubusercontent.com/u/25006490?v=4)](https://github.com/PrinsFrank "PrinsFrank (60 commits)")[![szepeviktor](https://avatars.githubusercontent.com/u/952007?v=4)](https://github.com/szepeviktor "szepeviktor (2 commits)")

---

Tags

containerpsr-11psr11

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

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

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

###  Alternatives

[pimple/pimple

Pimple, a simple Dependency Injection Container

2.7k130.5M1.4k](/packages/pimple-pimple)[league/container

A fast and intuitive dependency injection container.

86787.8M343](/packages/league-container)[lctrs/psalm-psr-container-plugin

Let Psalm understand better psr11 containers

17648.1k13](/packages/lctrs-psalm-psr-container-plugin)[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)
