PHPackages                             noem/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. [Framework](/categories/framework)
4. /
5. noem/container

ActiveLibrary[Framework](/categories/framework)

noem/container
==============

Modular service container

0259[1 PRs](https://github.com/NoemPHP/container/pulls)PHPCI failing

Since Oct 25Pushed 1y agoCompare

[ Source](https://github.com/NoemPHP/container)[ Packagist](https://packagist.org/packages/noem/container)[ RSS](/packages/noem-container/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependenciesVersions (2)Used By (0)

Noem Container
==============

[](#noem-container)

A modern auto-wiring service container that leverages PHP8 Attributes to tag and interlink services with their dependencies.

It features:

- Aggregating services from multiple modules using a service provider pattern
- Comprehensive support for auto-wiring strategies leveraging [php-di/invoker](https://github.com/PHP-DI/Invoker)
- Resolution of circular dependencies by automatically injecting lightweight proxy objects

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

[](#installation)

Install this package via composer:

`composer require noem/container`

Usage
-----

[](#usage)

The container works by assimilating service factory functions from one or more Service Providers. A `Provider` looks like this:

```
interface Provider
{

    /**
     * Returns a list of all container entries registered by this service provider.
     *
     * - the key is the entry name
     * - the value is a callable that will return the entry, aka the **factory**
     *
     * Factories have the following signature:
     *        callable( mixed... ):mixed
     * Factories can declare any number & type of parameters and can expect them to be resolved by the Container
     *
     * @psalm-return array
     * @return callable[]
     */
    public function getFactories(): array;

    /**
     * Returns a list of all container entries extended by this service provider.
     *
     * - the key is the entry name
     * - the value is a callable that will return the modified entry
     *
     * Callables have the following signature:
     *        function( mixed $previous, mixed ...$params )
     * The $previous parameter MUST be the first one. Additional parameters will be resolved by the Container.

     * @psalm-return array
     * @return callable[]
     */
    public function getExtensions(): array;
}
```

Attributes
----------

[](#attributes)

PHP 8 introduced [a new feature called Attributes](https://stitcher.io/blog/attributes-in-php-8) that allows adding arbitrary metadata to classes, functions, methods and parameters. This provides us with a lot of flexibility when writing service definitions.

During service compilation, the container will parse all function attributes and make them available for manual and automatic resolving of dependencies by implementing `AttributeAwareContainer`:

```
interface AttributeAwareContainer extends ContainerInterface
{
    public function getIdsWithAttribute(string $attribute, ?callable $matching = null): array;

    public function getAttributesOfId(string $id, ?string $attributeFQCN = null): array;
}
```

### Service-level Attributes

[](#service-level-attributes)

#### Alias

[](#alias)

> Example: `#[Alias( 'my-other-service-id' )]`

Use this to advertise your service under a number of IDs without repeating the definition. One use-case is to encourage interface segregation in consumers while supplying them with a class that implements multiple interfaces:

```
class MyContainer implements ContainerInterface, WritableContainerInterface, FlushableContainerinterface {
   // ...
}
```

The service can be defined as follows:

```
MyContainer::class =>
    #[Alias(ContainerInterface::class)]
    #[Alias(WritableContainerInterface::class)]
    #[Alias(FlushableContainerinterface::class)]
    fn() => new MyContainer()
```

The container is now able to resolve any of the interface FQCNs to the instance of `MyContainer`:

```
// These all return the same instance:
$container->get(MyContainer::class);
$container->get(ContainerInterface::class);
$container->get(WritableContainerInterface::class);
$container->get(FlushableContainerinterface::class);
```

#### Tag

[](#tag)

> Example: `Tag( 'event-listener' )`

You can use this attribute as a low-coupling way to implement extensible "lists of things". A natural application for this would be to wire up event subscribers to a PSR-14 ListenerProvider

```
$services = [
    'listener.all' =>
        #[Tag('event-listener')]
        fn( LoggerInterface $logger ) => function( object $event ) use ($logger){
            $logger->info( 'Event triggered: ' . print_r( $event, true ) );
        },
];
```

The Tag attribute also supports specifying an optional `priority` which is used to sort services before they are passed to consumers. The default priority is `50`

> Example: `Tag( 'event-listener', 10 )`

### Parameter-level Attributes

[](#parameter-level-attributes)

#### Id

[](#id)

> Example: `#[Id( 'service-id' )]`

Can be used on parameters of factories/extension functions. It instructs the Container to resolve the parameter by fetching the specified entry. Takes precedence over other means of parameter resolution

```
$services = [
    'my-string' => fn() => 'hello',
    'greeting' =>
        fn(#[Id('my-string')] string $string) => "{$string} world",
];

$container = new Container(new ServiceProvider($services));
$greeting = $container->get('greeting'); // 'hello world'
```

#### WithAttr

[](#withattr)

> Example: `#[WithAttr( MyCustomAttr::class )]`

Resolves to all services that have been annotated with the specified Attribute. You can optionally pass a map of key/value pairs that will be used for filtering results.

> Example: `#[WithAttr( MyCustomAttr::class, [ 'name' => 'foo' ] )]`

This will return only those services that are annotated with `#[MyCustomAttr('foo')]` (provided that `foo` maps to the attribute's `name` property of course)

#### TaggedWith

[](#taggedwith)

> Example: `#[TaggedWith( 'foo' )]`

This is is a shorthand for `WithAttr( Tag::class, [ 'name' => $MY_TAG ] )` to fetch all services with the specified tag.

```
$services = [
    ListenerProviderInterface:: =>
        fn(#[TaggedWith('event-listener')] callable ...$listeners) => new ListenerProvider(...$listeners),
];
```

###  Health Score

18

—

LowBetter than 8% of packages

Maintenance32

Infrequent updates — may be unmaintained

Popularity11

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity19

Early-stage or recently created project

 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/16e124446e13d0c8773106688a571f7afc645474750a5d8e7489e568f67d2822?d=identicon)[Biont](/maintainers/Biont)

---

Top Contributors

[![Biont](https://avatars.githubusercontent.com/u/4208996?v=4)](https://github.com/Biont "Biont (47 commits)")

### Embed Badge

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

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

###  Alternatives

[laravel/telescope

An elegant debug assistant for the Laravel framework.

5.2k67.8M192](/packages/laravel-telescope)[spiral/roadrunner

RoadRunner: High-performance PHP application server and process manager written in Go and powered with plugins

8.4k12.2M84](/packages/spiral-roadrunner)[nolimits4web/swiper

Most modern mobile touch slider and framework with hardware accelerated transitions

41.8k177.2k1](/packages/nolimits4web-swiper)[laravel/dusk

Laravel Dusk provides simple end-to-end testing and browser automation.

1.9k36.7M259](/packages/laravel-dusk)[laravel/prompts

Add beautiful and user-friendly forms to your command-line applications.

708181.8M596](/packages/laravel-prompts)[cakephp/chronos

A simple API extension for DateTime.

1.4k47.7M121](/packages/cakephp-chronos)

PHPackages © 2026

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