PHPackages                             bapcat/phi - 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. bapcat/phi

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

bapcat/phi
==========

A super-minimal inversion-of-control library

4.0.1(2y ago)11.2k[2 issues](https://github.com/BapCat/Phi/issues)8GPL-3.0-or-laterPHPPHP ^7.4|^8.0

Since Jun 14Pushed 2y ago3 watchersCompare

[ Source](https://github.com/BapCat/Phi)[ Packagist](https://packagist.org/packages/bapcat/phi)[ Docs](https://github.com/BapCat/Phi)[ RSS](/packages/bapcat-phi/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (8)Dependencies (4)Versions (10)Used By (8)

[![Build Status](https://camo.githubusercontent.com/2f55a9fe399d840e2108ec8ee0395a3c1b77b389b9bd17349b39488fe8f74ba7/68747470733a2f2f7472617669732d63692e6f72672f4261704361742f5068692e7376673f6272616e63683d322e302e30)](https://travis-ci.org/BapCat/Phi)[![Coverage Status](https://camo.githubusercontent.com/ad9b70dae3d3ea64bc76a00c400367717fee05342191034fe492dfc23ffe731f/68747470733a2f2f636f766572616c6c732e696f2f7265706f732f4261704361742f5068692f62616467652e7376673f6272616e63683d322e302e30)](https://coveralls.io/r/BapCat/Phi?branch=2.0.0)[![License](https://camo.githubusercontent.com/d929084597b88735ce278e0864e6bbb6d196fe2735443d8ffaff1304efc204dd/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f4261704361742f5068692e737667)](https://img.shields.io/packagist/l/BapCat/Phi.svg)

φhi
===

[](#φhi)

An efficient, easy-to-use, open-source PHP dependency injection container, boasting a tiny footprint, powerful features, 100% unit test coverage, and awesome documentation. Phi is compatible with PSR-0 and PSR-4 auto-loading standards, and open to collaboration from anyone who feels they can make an improvement.

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

[](#installation)

### Composer

[](#composer)

[Composer](https://getcomposer.org/) is the recommended method of installation for BapCat packages.

```
$ composer require bapcat/phi

```

### GitHub

[](#github)

BapCat packages may be downloaded from [GitHub](https://github.com/BapCat/Phi/).

Features
--------

[](#features)

Phi supports several different ways to inject dependencies, which can all be used alone or in conjunction with one another.

### Automatic Injection

[](#automatic-injection)

Assume you have a class named `Foo` that depends on a second class, `Bar`:

```
class Foo {
  public $bar = null;

  public function __construct(Bar $bar) {
    $this->bar = $bar;
  }
}
```

You can easily get a new instance of `Foo` with all required dependencies by doing the following:

```
$foo = $phi->make(Foo::class);
// $foo->bar = new Bar
```

You'll get a new instance of `Foo` with a new instance of `Bar` automatically injected into the constructor. This, of course, works recursively. If `Bar` depends on `Baz`, an instance of `Baz` will be injected into `Bar`, and so on.

### Passing Parameters

[](#passing-parameters)

There will be many cases where you need to pass parameters into the constructors as well. Consider the following class (note the order of the parameters):

```
class Foo {
  public $a;
  public $b;
  public $first_name;
  public $last_name;

  public function __construct(B $b, A $a, $first_name = null, $last_name = null) {
    $this->a = $a;
    $this->b = $b;
    $this->first_name = $first_name;
    $this->last_name  = $last_name;
  }
}
```

There are several ways you can request this class from Phi:

```
$foo = $phi->make(Foo::class);
// $foo->a == new A
// $foo->b == new B
// $foo->first_name == null
// $foo->last_name  == null
```

```
$foo = $phi->make(Foo::class, ['John', 'Doe']);
// $foo->a == new A
// $foo->b == new B
// $foo->first_name == 'John'
// $foo->last_name  == 'Doe'
```

```
$foo = $phi->make(Foo::class, ['John']);
// $foo->a == new A
// $foo->b == new B
// $foo->first_name == 'John'
// $foo->last_name  == null
```

You may want to override an automatically injected parameter:

```
$a = new A;
$foo = $phi->make(Foo::class, ['John', 'Doe', $a]);
// $foo->a == $a
// $foo->b == new B
// $foo->first_name == 'John'
// $foo->last_name  == 'Doe'
```

Note that `$a` was passed in last in the previous example. Phi is smart enough to figure out the correct order to inject parameters of non-scalar types.

### Multiple Same-Type Dependencies

[](#multiple-same-type-dependencies)

Consider the following class:

```
class Foo {
  public function __construct(BarInterface $bar, A $a, BarInterface $baz, B $b) {
    // ...
  }
}
```

```
$bar = new Bar; // implements BarInterface
$baz = new Baz; // implements BarInterface
$foo = $phi->make(Foo::class, [$bar, $baz]);
// $foo->bar == $bar
// $foo->baz == $baz
// $foo->a   == new A
// $foo->b   == new B
```

Parameters of the same type will be passed to the constructor in the order they are given to Phi. If you would like to pass them in a different order, please see the section on [named injection](https://github.com/BapCat/Phi#named-injection).

### Named Injection

[](#named-injection)

In some cases, it is useful to be explicit about which parameters you are passing in. Phi makes this easy. Consider the class from the "Passing Parameters" section:

```
class Foo {
  public function __construct(A $a, B $b, $first_name = null, $last_name = null) {
    // ...
  }
}
```

```
$a = new A;
$b = new B;
$foo = $phi->make(Foo::class, [$b, 'last_name' => 'Doe', $a]);
// $foo->a == $a
// $foo->b == $b
// $foo->first_name == null
// $foo->last_name  == 'Doe'
```

### Binding

[](#binding)

Many modern applications have pieces that may be swapped out. This is accomplished by using interfaces. Phi allows automatic injection of interfaces using binding:

```
interface BarInterface {

}

class Bar implements BarInterface {

}

class Foo {
  public function __construct(BarInterface $bar) {
    // ...
  }
}

$phi->bind(BarInterface::class, Bar::class);
```

```
$foo = $phi->make(Foo::class);
// $foo->bar == new Bar
```

```
$bar = $phi->make(BarInterface::class);
// $bar = new Bar
```

Binding even allows you to swap one concrete instance of a class for another:

```
$phi->bind(A::class, B::class);

$a = $phi->make(A::class);
// $a == new B
```

### Dependencies With Parameters

[](#dependencies-with-parameters)

Sometimes you may have a dependency that has required parameters. This can be done by binding a class to a callable:

```
$phi->bind(Person::class, function() {
  return new Person('John', 'Doe');
});

$person = $phi->make(Person::class);
// $person->first_name == 'John'
// $person->last_name  == 'Doe'
```

This is also useful if you need to perform logic when instanciating a class:

```
$id = 0;

$phi->bind(Person::class, function() use(&$id) {
  return new Person(++$id);
});

$person1 = $phi->make(Person::class); // id == 1
$person2 = $phi->make(Person::class); // id == 2
```

Any parameters passed to Phi will be passed directly to the callable:

```
$id = 0;

$phi->bind(Person::class, function($name, $age) use(&$id) {
  $names = explode(' ', $name);
  return new Person(++$id, $name[0], $name[1], $age);
});

$person = $phi->make(Person::class, ['John Doe', 21]);
// $person->id == 1
// $person->first_name == 'John'
// $person->last_name  == 'Doe'
// $person->age == 21
```

### Singletons

[](#singletons)

Phi also allows binding to real instances of classes. This can be used to create singletons:

```
$default_pdo = new PDO(...); // The default database
$stats_pdo   = new PDO(...); // PDO pointing to a different database

$phi->bind(PDO::class, $default_pdo);
```

```
$pdo = $phi->make(PDO::class);
// $pdo == $default_pdo
```

```
class Table {
  public function __construct(PDO $pdo, $table_name) {
    // ...
  }
}

$users_table = $phi->make(Table::class, ['users']);
// $users_table->pdo   == $default_pdo
// $users_table->table == 'users'

$stats_table = $phi->make(Table::class, [$stats_pdo, 'stats']);
// $stats_table->pdo   == $stats_pdo
// $stats_table->table == 'stats'
```

### Aliases

[](#aliases)

Sometimes, a codebase will have very commonly used classes with difficult-to remember names. For example, `Vendor\Package\Core\Logging\Log`. It may be useful to give such classes shorter and easier to type names:

```
$phi->bind('core.log', \Vendor\Package\Core\Logging\Log::class);

$log = $phi->make('core.log');
// $log == new Vendor\Package\Core\Logging\Log
```

You may also bind aliases to callables or singletons.

### Custom Resolvers

[](#custom-resolvers)

There may be times when you want to match far more than a single alias. Custom resolvers were designed with this purpose in mind. When a binding is requested from Phi, any custom resolvers that are registered will be executed one by one in the order they were added, and the first one to return a non-null value is the one that will be used. If all custom resolvers return null, Phi will resolve the binding normally.

```
use BapCat\Interfaces\Ioc\Resolver;

class CustomResolver implements Resolver {
  public function make($alias, array $arguments = []) {
    if($alias == A::class) {
      return new B(new A());
    }
  }
}

$phi->addResolver(new CustomResolver());
```

```
$b = $phi->make(A::class);
//$b == new B
```

Another reason to use custom resolvers is to wrap other IoC containers. For example, if you are using Laravel, you could combine the Laravel container with Phi:

```
use Illuminate\Support\Facades\App;
use BapCat\Interfaces\Ioc\Resolver;

class LaravelResolver implements Resolver {
  public function make($alias, array $arguments = []) {
    if(App::bound($alias)) {
      return App::make($alias, $arguments);
    }
  }
}

$phi->addResolver(new LaravelResolver());
```

This way, any binding that is registered in the Laravel IoC container will be resolved by it. The rest will be passed on to Phi.

### Recursive Resolution

[](#recursive-resolution)

It's possible to bind one binding to another.

```
$ioc->bind(FooInterface::class, Foo::class);
$ioc->bind('bap.foo', FooInterface::class);

### Singletons
While it's possible to bind an alias to an instance of a class, effectively creating a singleton, it's not always
desirable (or possible) to load all singletons at boot time.  Instead, singletons can be registered and lazy-loaded.

```php
$phi->singleton(FooInterface::class, Foo::class);
```

The first time an instance of `FooInterface` is requested, `Foo` will be loaded and bound. From then on, all requests for `FooInterface` will return the same instance of `Foo`.

### Dependency Injection on Callables

[](#dependency-injection-on-callables)

Not only is dependency injection useful when creating objects, it may also be useful when calling methods. Phi can perform dependency injection on any method PHP will accept as a `callable` type hint.

```
$phi->call([$instance, 'method']);
$phi->call([Class::class, 'staticMethod']);
$phi->call(['Class::staticMethod']);
$phi->call($invokableClass);
$phi->call(function(FooInterface $foo) { });
$phi->call('var_dump', [$foo]);
```

You may pass arguments to method injections in the same way as constructor injections.

###  Health Score

31

—

LowBetter than 68% of packages

Maintenance0

Infrequent updates — may be unmaintained

Popularity19

Limited adoption so far

Community18

Small or concentrated contributor base

Maturity74

Established project with proven stability

 Bus Factor1

Top contributor holds 97.5% 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 ~417 days

Recently: every ~711 days

Total

8

Last Release

1070d ago

Major Versions

1.2.0 → 2.0.02015-09-15

2.0.0 → 3.0.02019-01-03

3.0.0 → 4.0.02021-02-18

PHP version history (4 changes)1.0.0PHP &gt;=5.4.0

1.1.1PHP &gt;=5.5.0

3.0.0PHP ^7.1

4.0.0PHP ^7.4|^8.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/246ea082e8ed7f6e8ace29950179d4dfb1e3a58bac53aef49a3d2e43ab1e7f04?d=identicon)[LordMonoxide](/maintainers/LordMonoxide)

---

Top Contributors

[![LordMonoxide](https://avatars.githubusercontent.com/u/437657?v=4)](https://github.com/LordMonoxide "LordMonoxide (78 commits)")[![crossbap](https://avatars.githubusercontent.com/u/18564250?v=4)](https://github.com/crossbap "crossbap (2 commits)")

---

Tags

dependency-injectiondiiocinversion of control

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/bapcat-phi/health.svg)

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

###  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.

437730.3k17](/packages/level-2-dice)[mouf/mouf

The Mouf PHP framework: an open-source PHP framework providing an easy way to download, install, use and reuse components, with a graphical user interface.

55146.0k17](/packages/mouf-mouf)[capsule/di

A PSR-11 compliant autowiring dependency injection container.

2857.5k2](/packages/capsule-di)[x-wp/di

The dependency injection container for WordPress

301.1k10](/packages/x-wp-di)[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)
