PHPackages                             pyther/ioc - 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. pyther/ioc

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

pyther/ioc
==========

Inversion of Control Container

v0.1.5(1y ago)043MITPHPPHP &gt;=8.1

Since Jul 25Pushed 1y ago1 watchersCompare

[ Source](https://github.com/peterGdot/Pyther.Ioc)[ Packagist](https://packagist.org/packages/pyther/ioc)[ RSS](/packages/pyther-ioc/feed)WikiDiscussions main Synced today

READMEChangelog (6)DependenciesVersions (7)Used By (0)

Pyther.Ioc
==========

[](#pytherioc)

A simple lightweight PHP Inversion of Control (IoC) container with the following features:

- allow the creation of multiple or single(ton) instances
- goes hand in hand with *Constructor Dependency Injection*
- can bind to classes, methods, functions and instances
- trigger autoloader only during resolve phase (lazy loading)
- resolve nested dependencies, based on constructor DI
- can bind with optional arguments
- allow per instance arguments for non singletons during resolve phase
- detect cyclic dependencies on first use
- take default constructor arguments into account
- support for multiple, independent containers
- no external dependencies
- easy to use

Requirements
------------

[](#requirements)

- php 8.1 or higher

Quickstart
----------

[](#quickstart)

Install the [Composer Package](https://packagist.org/packages/pyther/ioc)

`composer require pyther/ioc`

*Inversion of Control* is a two way process. First you have to *bind* or *register* implementations of interfaces or classes to the container and then *resolve* (one or multile times) the creation of instances. And here is a fictional example:

```
use Pyther\Ioc\Ioc;

// Let's bind an implementation of “MariaDatabase” as a singleton to an interface.
// This ist afast process and will NOT trigger the autoloader.
Ioc::bindSingleton(IDatabase::class, MariaDatabase::class);

// later anywhere in your code, resolve to an instance of a MariaDatabase class
$db = Ioc::get(IDatabase::class);
```

Why using an Ioc container
--------------------------

[](#why-using-an-ioc-container)

An *IoC Container* simplifies the creation of instances. It resolves object dependencies and is optimized to create instances on first use (lazy loading). It also makes it possible to replace classes with other (mock) implementations by changing one line of code. And it works perfectly with constructor dependency injections, forcing you to write cleaner code. It can also replace "global" collection classes.

In short, you define how instances are to be created, not when.

Binding
-------

[](#binding)

There are two general ways to bind implementations to the container.

The full syntax is:

```
bind[Singleton|Multiple](string name, string|callable|null implementation, array arguments = []) -> Ioc
```

The `name` is a unique name used later by the `get` method. The `implementation` must be a string (class name), any callable construction method, and existing object or null. `arguments` is an optional array of constructor arguments, indexed by argument name. These methods will return the Ioc container itself (usefull for chaining).

### BindSingleton

[](#bindsingleton)

```
Ioc::bindSingleton(ShoppingCart::class, ShoppingCart::class);
```

If you bind using `bindSingleton` the instance will be created on first use of `Ioc::get(ShoppingCart::class)`. All subsequent calls to the `get` method will always return the same instance.

### BindMultiple

[](#bindmultiple)

```
Ioc::bindMultiple(Product::class, Product::class);
```

This way any call of `Ioc::get(Product::class)` will return a new instance of the `Product` class.

Dependency Injection
--------------------

[](#dependency-injection)

A "Inversion of Control" container goes hand in hand with [Constructor Dependency Injection](https://en.wikipedia.org/wiki/Dependency_injection#Constructor_injection).

Let's look at an example. Imagine we have a shopping cart that depends of the current logged in customer:

```
class ShoppingCart
{
    function __construct(Customer $customer)
    {
        ...
    }
}
```

If we bind the `ShoppingCart` and `Customer` class to the IoC container

```
// hint: the order of binding doesn't matter.
Ioc::bindSingleton(ShippingCart::class, ShoppingCart::class);
Ioc::bindSingleton(Customer::class, Customer::class);
```

and we resolve the `ShoppingCart` class using

```
$cart = Ioc::get(ShoppingCart::class);
```

the container want to create a new shopping cart and see it requires a customer class. For this reason, a `Customer` instance is first created (if not already done) and passed as a parameter to the constructor of the ShoppingCart. This nesting is recursive and takes “singletons” and “multiple” instances into account. Of course, multiple constructor arguments are supported and cyclic dependencies are recognized when resolving via the `get` method and fires a `Pyther\Ioc\Exceptions\ResolveException` exception.

More control
------------

[](#more-control)

This library gives you a lot control how objects will be instanced.

### More binding control

[](#more-binding-control)

For example you can add your own constructor arguments:

```
class Configurations
{
    function __construct(?string $path = null)
    {
        ...
    }
}
...
Ioc::bindSingleton(Configurations::class, Configurations::class, ["path" => "./config.json"]);
```

As you can see, the default values for constructors are taken into account (if no arguments are found).

Another way is to create an anonymous construct function:

```
Ioc::bindSingleton(Configurations::class, function() {
    return new Configurations("./config.json);
});
```

This function is only executed later when the object is first instantiated.

This way you can also have function arguments:

```
Ioc::bindSingleton(Configurations::class, function(string $path) {
    return new Configurations($path);
}, ['path' => "./config.json"]);
```

This construct function can be also be a static method of another object:

```
$this->bindSingleton(IInterface::class, [AnyClass::class, "createObject"]);
// or
$this->bindSingleton(IInterface::class, "My\Namespace\AnyClass::createObject");

or with arguments

$this->bindSingleton(IInterface::class, [AnyClass::class, "createObject"], [
    "text" => "abc", "number"=> 123
]);
// or
$this->bindSingleton(IInterface::class, "My\Namespace\AnyClass::createObject", [
    "text" => "abc", "number"=> 123
]);
```

Or as a method of an already instanced object:

```
$this->bindSingleton(IInterface::class, [$obj, "createObject"]);
// or with arguments
$this->bindSingleton(IInterface::class, [$obj, "createObject"],  [
    "text" => "abc", "number"=> 123
]);
```

Binding to zero is also legitimate:

```
Ioc::bindSingleton(Configurations::class, null);
```

In this case, an exception is not thrown when resolving, but is resolved to zero.

And finally you can also bind an already existing objects:

```
$configs = new Configurations("./config.json");
...
Ioc::bindSingleton(Configurations::class, $configs);
```

Although this is possible, it should be avoided. On the one hand, the creation of the instances should be left to the container, on the other hand this triggers the autoloader and executes code that may never be needed.

### More resolve control

[](#more-resolve-control)

For non singleton instances you can specifiy constructor arguments during the *resolve* phase:

```
class Product
{
    public function __construct(string $sku) {
        ...
    }
}
...
Ioc::bindMultiple(Product::class, Product::class);
...
Ioc::get(Product::class, ["sku" => "Product 001"];
...
Ioc::get(Product::class, ["sku" => "Product 002"];

```

Check if binding exists
-----------------------

[](#check-if-binding-exists)

To check if a binding exists, you can use the `has` method:

```
$exists = Ioc::has(Configurations::class);
```

Multiple Containers
-------------------

[](#multiple-containers)

If you have the rare case where you need more than one container, here we are.

The static methods of `Ioc::bindSingleton(...)`, `Ioc::bindMultiple(...)` and `Ioc::get(...)` are suggar forms of

```
IoC::$default->addMultiple(...)
IoC::$default->addSingleton(...)
IoC::$default->resolve(...)
```

where `Ioc::$default` is the default container. This way you can have separated multiple containers:

```
$containerA = new Ioc();
$containerB = new Ioc();

$containerA->addSingleton(...);
$containerB->addMutliple(...);

$containerA->get(...);
```

I'm sure you get it :)

###  Health Score

28

—

LowBetter than 52% of packages

Maintenance46

Moderate activity, may be stable

Popularity8

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity43

Maturing project, gaining track record

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

Recently: every ~73 days

Total

6

Last Release

415d ago

PHP version history (2 changes)v0.1.1PHP &gt;=8.2

v0.1.2PHP &gt;=8.1

### Community

Maintainers

![](https://www.gravatar.com/avatar/904a2f429f6b7e47ef87a331a8266be72a7e15970c2e0e28f8a257c2efbcb711?d=identicon)[peterGdot](/maintainers/peterGdot)

---

Top Contributors

[![peterGdot](https://avatars.githubusercontent.com/u/124894114?v=4)](https://github.com/peterGdot "peterGdot (17 commits)")

---

Tags

ioc-containerphp-libraryiocinversion of controlsingleton

### Embed Badge

![Health badge](/badges/pyther-ioc/health.svg)

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

###  Alternatives

[level-2/dice

A minimalist Dependency injection container (DIC) for PHP. Please note: 3.0+ is only compatible with PHP 7.0. The 2.0 branch is compatbile with PHP 5.6.

436797.2k21](/packages/level-2-dice)[florianwolters/component-util-singleton

The Singleton (and Registry of Singletons a.k.a. Multiton) design pattern as a PHP component.

13179.3k5](/packages/florianwolters-component-util-singleton)[acelot/resolver

Dependency auto resolver for PHP 7 and 8

122.7k](/packages/acelot-resolver)[michaels/data-manager

Simple data manager for nested data, dot notation array access, extendability, and container interoperability.

121.9k2](/packages/michaels-data-manager)

PHPackages © 2026

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