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

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

slava-basko/container
=====================

Dependency injection container.

3.0.0(6mo ago)01.8k↓30.8%MITPHPPHP &gt;=7.1CI passing

Since Mar 7Pushed 6mo ago1 watchersCompare

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

READMEChangelogDependencies (4)Versions (6)Used By (0)

Dependency Injection Container
==============================

[](#dependency-injection-container)

For those who understand what it is and strive for simplicity.

Zero dependencies and PHP 7.1+.

Features
--------

[](#features)

- Simple API: Container API is as simple as regular array.
- Tags: Organize services using tags and fetch them in groups (consider them aliases).
- Shared Instances: Easily create singletons with a built-in helper.
- Service Extenders: Modify/Extend services after creation and before they are fully resolved.
- Circular Dependency Detection: Automatically prevents and reports circular dependencies.
- Autowiring: Container will automatically resolve dependencies.
- Rewrite Protection: Reports about accidental service rewrite.
- Service Providers: Package your services into a provider for better organization.
- Symlinks: Runtime hot-swap.
- Graph: Generate DOT script to visualize dependencies (Graphviz).

### Simple API

[](#simple-api)

Consider `Container` as a regular array.

```
$container = new Container();

$container['cache-file-path'] = '/tmp/app.cache';
$container[CacheStorage::class] = fn (Container $c) => new CacheStorage($c['cache-file-path']);
$container[Cache::class] = fn(Container $c) => new Cache($c[CacheStorage::class]);

$cache = $container[Cache::class];

$cache->get('currency-rates');
```

Easier than ever for simple script/app.

### Tags

[](#tags)

Things get a bit more complicated when you need tags. Use the `Container::add()` method to setup tags.

```
$container = new Container();

$container['log-file-path'] = 'your.log';
$container->add('file-handler', fn (Container $c) => new StreamHandler($c['log-file-path']), ['handler']);
$container->add('stdout-handler', fn (Container $c) => new StreamHandler('php://output'), ['handler']);
$container[Logger::class] = function (Container $c) {
    $logger = new Logger('app');
    $logger->setHandlers($c->getByTag('handler'));

    return $logger;
};

$logger = $container[Logger::class];

$logger->warning('Oops!');
```

Use the `Container::getByTag()` method to retrieve services by tags. This separate method exists because regular `get` should return a specific service or throw a `NotFoundException`exception.

Clear and strict separation: `Container::get()` returns a service or throws `NotFoundException`, and the `Container::getByTag()` returns an array of services of throws `NotFoundException`.

#### Alias

[](#alias)

This container has no separate feature like `alias` for two main reasons.

- Container has a `tags` feature, basically `alias`.
- To keep container code as simple as possible.

Use tagging functionality to achieve the same `$service = $container->getByTag('tag')[0];`. Don't worry about `Warning: Undefined array key 0` because container does not return an empty array. It will return an array of services or throw `NotFoundException` like regular `get`.

Most likely, you want to use `alias` to avoid class name exposure. For example when you want to get service by requests param.

```
class GameController extends Controller {
    public function getPotion(string $potionType)
    {
        try {
            $potionService = $this->container->getByTag($potionType)[0];

            return new Response($potionService->getPotion());
        } catch (NotFoundException) {
            return new Response('Unknown potion type: ' . $potionType, 400);
        } catch (Exception $exception) {
            $this->logger->error($exception->getMessage());
            return new Response('Sorry, internal error', 500);
        }
    }
}
```

### Shared Instances

[](#shared-instances)

Use `Container::addShared()` method to create a shareable service. Container will return the same instance each time.

```
$container = new Container();

$container->addShared(MySQLConnection::class, fn (Container $c) => new MySQLConnection());

$conn1 = $container->get(MySQLConnection::class);
$conn2 = $container->get(MySQLConnection::class);

assert(spl_object_hash($conn1) === spl_object_hash($conn2));
```

### Service Extenders

[](#service-extenders)

Use `Container::extend()` to modify services by a common parent.

```
$container = new Container();
$container[\Logger::class] = fn () => new \Logger();
$container[\SomeRepository::class] = fn () => new \SomeRepository();
$container->extend(\BaseRepository::class, function (\BaseRepository $repository, Container $c) {
    $repository->setLogger($c[\Logger::class]);

    return $repository;
});

$repository = $container[\SomeRepository::class];
// From now on, every repository returned by the container and which `extends` BaseRepository has a Logger inside.
```

### Circular Dependency Detection

[](#circular-dependency-detection)

Container will let you know if you have a circular dependency.

```
$container = new Container();
$container[A::class] = fn (Container $c) => new \A($c[B::class]);
$container[B::class] = fn (Container $c) => new \B($c[A::class]);

$a = $container[\A::class];
// CircularDependencyException: Circular dependency detected: A -> B -> A
```

### Autowiring

[](#autowiring)

Use `AutowireContainer` for automatic dependency resolving.

```
class FilesystemAdapter {
    // some logic inside
}
class Filesystem {
    /**
     * @var \FilesystemAdapter
     */
    private $adapter;

    public function __construct(FilesystemAdapter $adapter)
    {
        $this->adapter = $adapter;
    }

    // use $this->adapter as you need
}

$container = new AutowireContainer();

$filesystem = $container[Filesystem::class]
// $filesystem will be an instance of Filesystem that contains FilesystemAdapter inside
```

### Rewrite Protection

[](#rewrite-protection)

Container will throw an exception if you accidentally rewrite the service definition.

```
$container = new Container();
$container['k'] = 'v1';
$container['k'] = 'v2'; // RewriteAttemptException: The resource 'k' already defined.
```

> *But what if I need to overwrite definition!*

Shift your mindset from "overwrite" to "setup based on X condition" and do it in the user-land code.

```
$container = new Container();
$container['mysql-dsn'] = getenv('ENVIRONMENT') === 'prod' ? 'mysql://production-dsn' : 'mysql://development-dsn';
```

This approach, together with `Rewrite Protection,` will keep your code strict and more understandable. There will be no hidden overwrites.

### Service Providers

[](#service-providers)

Providers give you the benefit of organizing your definitions.

```
class LoggerServiceProvider {
    public function __invoke(Container $container): void
    {
        // Define your handlers, formatters, processors, and logger itself.
        // All Logger-related things are in one place.
    }
}
```

Then, add the provider to the container.

```
$container->addProvider(new LoggerServiceProvider());
```

### Symlinks

[](#symlinks)

You can create symlinks that allow you to get different services on the run, without changing user-land code.

```
$container = new Container();
$container->add(MasterMySqlClient::class, fn (Container $c) => new MasterMySqlClient($c['mysql-dsn']));
$container->add(SlaveMySqlClient::class, fn (Container $c) => new SlaveMySqlClient($c['mysql-dsn']));

$container->symlink(MasterMySqlClient::class, MySqlInterface::class);
$container->get(MySqlInterface::class); // MasterMySqlClient

$container->symlink(SlaveMySqlClient::class, MySqlInterface::class);
$container->get(MySqlInterface::class); // SlaveMySqlClient
```

**Note:** Only one symlink to a specific service can exist at a time.

### Graph

[](#graph)

Using the DOT language, build a graph (as in nodes and edges, not as in bar charts). **Note:** Graph not working with `AutowireContainer`.

```
$container = new Container();
// Add services and define dependencies

$graph = new Graphviz($container);
$graph->build();
```

For example, you can visualize the output of `Graphviz::build()` with .

Graph element explanation:

- Oval — parameter
- Solid Rectangle — service
- Dashed Rectangle — shared service
- Parallelogram — non-existent service or param

[![graphviz.png](graphviz.png)](graphviz.png)

PSR-11
------

[](#psr-11)

Install `psr/container` package first.

```
composer require psr/container
```

Then wrap `Container` in `PsrContainer` and pass it to whoever expected `Psr\Container\ContainerInterface`.

```
// Define services, dependencies, etc.
$container = new Container();

// Wrap it.
$psrContainer = new PsrContainer($container);

$service = $psrContainer->get(Service::class);
```

###  Health Score

35

—

LowBetter than 80% of packages

Maintenance69

Regular maintenance activity

Popularity21

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity36

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.

###  Release Activity

Cadence

Every ~63 days

Total

5

Last Release

183d ago

Major Versions

1.0.1 → 2.0.02025-04-05

2.1.0 → 3.0.02025-11-16

### Community

Maintainers

![](https://www.gravatar.com/avatar/6a8e37b4c52b1cfe4f5d64f420d21875ebdeb53954d6859d6d663038b95ef3cc?d=identicon)[slava-basko](/maintainers/slava-basko)

---

Top Contributors

[![slava-basko](https://avatars.githubusercontent.com/u/4376953?v=4)](https://github.com/slava-basko "slava-basko (31 commits)")

---

Tags

containerdependencyinjectiondiiocservice

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

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

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

###  Alternatives

[league/container

A fast and intuitive dependency injection container.

86387.8M343](/packages/league-container)[capsule/di

A PSR-11 compliant autowiring dependency injection container.

2857.5k2](/packages/capsule-di)[miladrahimi/phpcontainer

Dependency injection (IoC) container for PHP projects

1322.7k2](/packages/miladrahimi-phpcontainer)[slince/di

A flexible dependency injection container

20260.4k6](/packages/slince-di)

PHPackages © 2026

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