PHPackages                             intraworlds/service-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. [Utility &amp; Helpers](/categories/utility)
4. /
5. intraworlds/service-container

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

intraworlds/service-container
=============================

Lightweight yet powerful implementation of dependancy injection container with autowiring

0.10.0(1mo ago)076.1k↑78.6%1MITPHPPHP ^8.3CI passing

Since Nov 6Pushed 1mo ago1 watchersCompare

[ Source](https://github.com/peoplepath/service-container)[ Packagist](https://packagist.org/packages/intraworlds/service-container)[ RSS](/packages/intraworlds-service-container/feed)WikiDiscussions master Synced yesterday

READMEChangelog (10)Dependencies (18)Versions (26)Used By (0)

Lightweight yet powerful implementation of dependency injection container with autowiring.

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

[](#installation)

Use [Composer](https://getcomposer.org) to install the package:

```
composer require intraworlds/service-container

```

Config
------

[](#config)

The container is implementing standard PSR-11 interface. You can use it with autowiring out-of-the-box. However, sometimes you want to configure things which needs parameters (eg. DB connection).

```
// zero configuration required
$container = new ServiceContainer;
$container->get(ClassWithManyDependencies::class);

// bind factory of a value object
#[Bind(self::load(...))]
final class Config
{
  function __construct(private array $values)

  static function load(Filesystem $fs) : self
}

// by method
$container->bind(Config::class, Config::load(...));

// delay actual factory execution (eg. connection to DB) with lazy objects
// inline factories in attributes are possible since PHP 8.5
#[Lazy, Bind(fn(Config $config) => new Aws\S3\S3Client(['region' => $config->get('S3_REGION')]))]
final class S3
{
  public function __construct(private Aws\S3\S3Client $client)
}

// by methods
$container->bind(S3::class, fn(Config $config) => new Aws\S3\S3Client(['region' => $config->get('S3_REGION')]));
$container->lazy(S3::class);

// use alias to bind without factory
#[Alias(MemoryCache::class)]
interface Cache

// by method
$container->alias(Cache::class, MemoryCache::class);
```

### Composite types

[](#composite-types)

A parameter typed as a union or intersection (eg. `Cache|NullCache`, `Countable&Traversable`) is **not** autowired by trying each member. The container resolves it under the type's string key, so you must register it explicitly — otherwise a `CannotAutowireCompositType` is thrown.

```
// a constructor param typed `Cache|NullCache` must be bound under that exact string
$container->bind('Cache|NullCache', fn() => new NullCache);
```

Usage
-----

[](#usage)

It can be useful to manipulate with *Service Container* directly.

```
// get singleton using configured factories or auto-wiring
$container->get(S3::class) === $container->get(S3::class);

// make fresh instances
$container->make(Uri::class) !== $container->get(Uri::class);

// service is always available if it's possible to create it
$container->has(Config::class) === true;

// return service only if it was already initialized before, NULL otherwise
$container->instance(Transaction::class);

// same as `get()` but fails gracefully (to NULL)
$container->try('NonExisting') === null;

// register an already existing instance as a singleton
$container->set(Clock::class, new FrozenClock($now));

// remove a singleton and return it (NULL if it wasn't set)
$container->unset(Clock::class);

// obtain (and memoize) the resolved factory for an ID
$container->factory(S3::class); // instance of IW\ServiceContainer\ServiceFactory
```

Examples
--------

[](#examples)

### Auto wiring arbitrary callable

[](#auto-wiring-arbitrary-callable)

Internal `CallableFactory` is useful for resolving any dependencies of a *callable*. Especially it's useful for `init` template method. See following example.

```
abstract class Parent {
  function __construct(private Dependency $dependency, ServiceContainer $container) {
    if (method_exists($this, 'init')) {
      (new CallableFactory($this->init(...)))($container);
    }
  }
}

class Child extends Parent {
  function init(AnotherDependency $another) {
    // ...
  }
}
```

### Manual Wiring

[](#manual-wiring)

Sometimes you want to configure container manually. Let's consider following example on *Command Pattern*

```
interface OrderCommand
{
  function execute();
}

class OrderInvoker
{
  function __construct(private OrderCommand ...$commands) {}

  function execute() : void {
    array_walk($this->commands, fn($command) => $command->execute());
  }
}
```

With `IW\ServiceContainer` you have several options how to resolve `OrderInvoker`'s dependencies.

```
// an alias but that's no good for multiple commands
$container->alias('OrderInvoker', 'ReserveItems');

// external factory
$container->bind('OrderInvoker', function (IW\ServiceContainer $container) {
  return new OrderInvoker($container->get('ReserveItems'), $container->get('SendInvoice'));
});

// internal factory
$container->bind('OrderInvoker', OrderInvoker::create(...));

class OrderInvoker
{
  static function create(ReserveItems $reserveItems, SendInvoice $sendInvoice) : OrderInvoker {
    return new OrderInvoker($reserveItems, $sendInvoice);
  }
}

// wiring factory
$container->wire('OrderInvoker', 'ReserveItems', 'SendInvoice');

// ...same but with attribute
#[Wire('OrderInvoker', 'ReserveItems', 'SendInvoice')]
class OrderInvoker
{
}
```

Arguably all approaches have their advantages. *internal factory* approach is good for static analysis. *wiring factory* is useful for common application pattern and when dependencies may vary.

Errors
------

[](#errors)

All exceptions extend `IW\ServiceContainer\Exception`, which implements PSR-11's `ContainerExceptionInterface`; `ServiceNotFound` additionally implements `NotFoundExceptionInterface`. When a failure is wrapped (eg. a broken dependency deep in a resolution chain), `Exception::getOrigin()` returns the first original exception raised outside the container, which is handy for pinpointing the root cause.

License
-------

[](#license)

All contents of this package are licensed under the [MIT license](LICENSE).

###  Health Score

56

—

FairBetter than 97% of packages

Maintenance94

Actively maintained with recent releases

Popularity28

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity77

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 ~115 days

Recently: every ~272 days

Total

25

Last Release

31d ago

PHP version history (4 changes)v0.6PHP ^7.2

v0.6.3PHP ^7.2||^8.0

v0.8PHP ^8.0

v0.9.0PHP ^8.3

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/2031969?v=4)[Ondřej Ešler](/maintainers/esler)[@esler](https://github.com/esler)

---

Top Contributors

[![esler](https://avatars.githubusercontent.com/u/2031969?v=4)](https://github.com/esler "esler (28 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

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

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

###  Alternatives

[symfony/dependency-injection

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

4.2k455.6M9.6k](/packages/symfony-dependency-injection)[symfony/service-contracts

Generic abstractions related to writing services

2.6k914.7M605](/packages/symfony-service-contracts)[illuminate/contracts

The Illuminate Contracts package.

706130.3M13.3k](/packages/illuminate-contracts)[illuminate/container

The Illuminate Container package.

31182.0M2.4k](/packages/illuminate-container)[api-platform/core

Build a fully-featured hypermedia or GraphQL API in minutes!

2.6k51.2M338](/packages/api-platform-core)[deptrac/deptrac

Deptrac is a static code analysis tool that helps to enforce rules for dependencies between software layers.

3.0k8.8M118](/packages/deptrac-deptrac)

PHPackages © 2026

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