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

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

grithin/ioc-di
==============

IoC DI with service container

0.10(4y ago)0141GPL-3.0-onlyPHPPHP &gt;=5.3.0

Since Jul 19Pushed 1y ago1 watchersCompare

[ Source](https://github.com/grithin/php-ioc-di)[ Packagist](https://packagist.org/packages/grithin/ioc-di)[ Docs](https://github.com/grithin/php-ioc-di)[ RSS](/packages/grithin-ioc-di/feed)WikiDiscussions master Synced today

READMEChangelogDependencies (3)Versions (11)Used By (1)

IoC DI
======

[](#ioc-di)

A small IoC Dependency Injector and Service Locator with experimental features, including a Data Locator.

```
composer require grithin/ioc-di
```

Use
---

[](#use)

### HEADER

[](#header)

For the code examples, use this header to run

```
# HEADER #
use \Grithin\{ServiceLocator, DependencyInjector};
use \Grithin\IoC\{NotFound, ContainerException, MissingParam, Datum, Service, Call, Factory};

$sl = new ServiceLocator;
$di = $sl->injector();
```

### Basic

[](#basic)

Service Locator injection of "NameInterface" typed parameter into newly constructed "Creature"

```
## INSERT HEADER ##

class Creature{
	public $name;
	public function __construct(NameInterface $name){
		$this->name = $name;
	}
}
interface NameInterface{ }
class Name implements NameInterface{
	public $text;
	public function __construct($text='bob'){
		$this->text = $text;
	}
}

$sl = new ServiceLocator;
$di = $sl->injector();

# add "Name" into services
$sl->bind('Name');

# construct "Creature" with injected Name instance
$bob = $di->call('Creature');
echo $bob->name->text;
#> 'bob'
```

### Mixing Service Locator And Provided Parameters

[](#mixing-service-locator-and-provided-parameters)

Sometimes it is useful to allow the ServiceLocator to find one parameter, to but provide another parameter instead of using the ServiceLocator for it.

```
## INSERT HEADER ##

class Creature{
	public $name;
	public $age;
	public function __construct(Name $name, Age $age){
		$this->name = $name;
		$this->age = $age;
	}
}
class Name{
	public $text;
	public function __construct($text='bob'){
		$this->text = $text;
	}
}
class Age{
	public $text;
	public function __construct($text='20'){
		$this->text = $text;
	}
}

# add "Age" into services
$sl->bind('Age');

# pass in the $age parameter by matching the parameter name
$bob = $di->call_with('Creature', ['age'=> new Age('30')]);
echo $bob->age->text;
#> 30

# pass in the $age parameter by matching the position
$bob = $di->call_with('Creature', [1=> new Age('30')]);
echo $bob->age->text;
#> 30
```

### Defaults

[](#defaults)

If the DependencyInjector can't resolve a dependency, you can provide a fallback default for the parameter.

```
## INSERT HEADER ##

class Creature{
	public $name;
	public function __construct(NameInterface $name){
		$this->name = $name;
	}
}
interface NameInterface{ }
class Name implements NameInterface{
	public $text;
	public function __construct($text='bob'){
		$this->text = $text;
	}
}

# use a default for the "name" parameter
$bob = $di->call('Creature', ['defaults'=>['name'=> new Name('Sue')]]);
# since "Name" has not been registered as a service, ServiceLocator will fail to find it, and use the default provided
echo $bob->name->text;
#> sue
```

Because it may be undesirable to first instantiate a default prior to it being used, special classes are available to prevent pre-instantiation.

These special classes include

- \\Grithin\\IoC\\Service
- \\Grithin\\IoC\\Datum
- \\Grithin\\IoC\\Call
- \\Grithin\\IoC\\Factory

See the [Special Types](#special-types)

Special Types
-------------

[](#special-types)

Using Grithin\\IoC\\SpecialTypeInterface

### Service Object

[](#service-object)

Used by: SL, DI

- If you want to point to a service with options.
- If you want to provide a parameter default as an object, but don't want to instantiate the object unless it is for default

Example of using `Service` for a default

```
## INSERT HEADER ##

interface NameInterface{}
class Name implements NameInterface
{
	public $text;
	public function __construct($text = 'bob')
	{
		$this->text = $text;
	}
}
function sayName(NameInterface $name){
	echo $name->text;
}

# create a service with pre-set construction options
$name_service = new Service(Name::class, ['with'=>['text'=>'sue']]);

# injector will fall back on the default, $name_service, since no NameInterface is registered
$di->call('sayName', ['defaults'=> ['name'=>$name_service]]);
#> sue
```

### Datum

[](#datum)

Used by: SL, DI

- If you want configure a service to be instantialized using datum that might be set later or change

```
## INSERT HEADER ##

class Person{
	public $name;
	function __construct($name){
		$this->name = $name;
	}
	function sayName(){
		echo $this->name;
	}
}

# Bind service id Person to the Person class, with constructor parameter using Datum "name"
$sl->bind('Person', Person::class,  ['with'=>['name'=>new Datum('name')]]);

# define the Datum for the DataLocator
# this is one benefit to using Datum - it can be defined after a service is bound to use it
$sl->data_locator->set('name', 'sue');

function sayName(Person $person){
	return $person->sayName();
}

# getName will cause ServiceLocator to create Person instance, which causes DataLocator to pull "name"
$di->call('sayName');
#> sue

# change Datum resolution
$sl->data_locator->set('name', 'bob');

# a new Person instance will be made, and Datum "name" will now resolve to "bob"
$di->call('sayName');
#> bob
```

### Call

[](#call)

Used by: SL, DI, DL

- If you want to point to the result of some callable.

```
## INSERT HEADER ##

class Person{
	public $name;
	function __construct($name){
		$this->name = $name;
	}
	function sayName(){
		echo $this->name;
	}
}

function getName() {
	return 'bob';
}

# Invoke getName when instantiating "Person" for parameter $name
$sl->bind('Person', Person::class,  ['with'=>['name'=>new Call('getName')]]);

function sayName(Person $person){
	return $person->sayName();
}

$di->call('sayName');
#> bob
```

### Factory

[](#factory)

Used by: SL, DI, DL

- Used to indicate to DataLocator it should use thing as a factory.

Whereas, with `Call`, a datum will be resolved by calling, with `Factory`, it will be resolved by calling every time the data is accessed from the DataLocator

```
## INSERT HEADER ##

$random = function(){ return rand(0,20000); };
$sl->data_locator->set('rand', new Call($random));
echo $sl->data_locator->get('rand');
#> 1231

# the DataLocator only runs the callable once, so it will return the same value here
echo $sl->data_locator->get('rand');
#> 1231

# a factory can be used to get new data every time
$sl->data_locator->set('rand', new Factory($random));

echo '|';
echo $sl->data_locator->get('rand');
echo '|';
#> 3421
echo $sl->data_locator->get('rand');
#> 8291
```

Resolution Of Parameters
------------------------

[](#resolution-of-parameters)

For some method definition, how does the injector resolve the injection values?

- if `with` variant/option is used (`call_with` and `call(..., ['with'=>[]]))`, use `with` array
    - by position
    - by name
- by type declaration (ServiceLocator)
- if parameter starts with uppercase, attempt to match against
    - Service
    - Datum
- if `defaults` option is present, use it
- use the default provided in the method/constructor definition

Parameter Name Based Resolution
-------------------------------

[](#parameter-name-based-resolution)

As a shortcut for well-known frequently used expected parameters, injection can use the name alone so long as that name starts with a capital letter. And, in this case, both services and data are checked.

```
## INSERT HEADER ##

$sl->data_locator->set('Server', 'localhost');

function printServer($Server){
	echo $Server;
}

$bob = $di->call('printServer');
#> localhost
```

Static analysis and autocompletion within editors has made this usually a bad option.

ServiceLocator
--------------

[](#servicelocator)

*Beyond The Basics*

### Singleton

[](#singleton)

For something like a Database, it is desirable that only one primary instance be created.

```
## INSERT HEADER ##
class Database{
	function __construct(){
		echo 'connecting... ';
		# ... expensive connection stuff ...
	}
	function query(){
		return 'bob';
	}
}

$sl->singleton('Database');

function getUserName(Database $db){
	echo $db->query();
}

$di->call('getUserName');
#> connecting... bob
$di->call('getUserName');
#> bob
```

You can also just provide an existing singleton object to the ServiceLocator

```
## INSERT HEADER ##
class Database{
	public $host;
	function __construct($host = 'local_899') {
		$this->host = $host;
	}
}

function getDb(Database $db){
	echo $db->host;
}

# Can use the `Service` class to override service config
$config = ['i'=>0];
$sl->singleton('Database', new Database('remote'));
$di->call('getDb');
#> remote
```

### Links

[](#links)

It may be useful to link one service id to another service

```
## INSERT HEADER ##
interface DatabaseInterface {}
class Database implements DatabaseInterface{
	function query(){
		return 'bob';
	}
}

$sl->bind('DatabaseInterface', 'LinkMiddleMan');
$sl->bind('LinkMiddleMan', 'Database');

function getUserName(DatabaseInterface $db){
	echo $db->query();
}

# ServiceLocator will resolve DatabaseInterface to LinkMiddleMan, and then LinkMiddleMan to Database
$di->call('getUserName');
#> bob
```

### Special Types

[](#special-types-1)

It may be useful to resolve a service using a special type.

Here, a function is used to get a service

```
## INSERT HEADER ##

class Database{
	function query(){
		return 'bob';
	}
}
function getDatabase(){
	return new Database;
}

function getUserName(Database $db){
	echo $db->query();
}

# Using the `Call` class
$sl->bind('Database', new Call('getDatabase'));
$di->call('getUserName');
#> bob

# Using a closure
$sl->bind('Database', function(){ return getDatabase(); });
$di->call('getUserName');
#> bob
```

Using `Service` for special configuration

```
interface DatabaseInterface {}
class Database implements DatabaseInterface {
	public $host;
	function __construct($host='local_899'){
		$this->host = $host;
	}
}

function getDb(DatabaseInterface $db){
	echo $db->host;
}

# Can use the `Service` class to override service config
$sl->bind('Database');
$sl->bind('DatabaseInterface', new Service('Database', ['with'=>['host'=>'remote_123']]));
$di->call('getDb');
#> remote_123
```

Data Locator
------------

[](#data-locator)

A service locator for data.

```
# basic
$sl->data_locator->set('x', '123');

# lazy loaded (called once)
$sl->data_locator->set('y', function(){ return '456'; });
function return_456(){
	return '456'
}
$sl->data_locator->set('y', new Call('return_456'));

# factory (called every time)
$sl->data_locator->set('y', new Factory('return_456'));
```

Notes
-----

[](#notes)

By default, SL does not check all classes to resolve an interface or abstract class, it only checks what is within the services (by id) or available without further file inclusion. You can make it check everything though:

```
$sl = new ServiceLocator(['check_all'=>true]);
```

###  Health Score

22

—

LowBetter than 22% of packages

Maintenance26

Infrequent updates — may be unmaintained

Popularity6

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity42

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

Total

10

Last Release

1748d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/4543facab3c88d548b98d8472b532faf7bcd00555cc47c0dc808d935f8d3d73f?d=identicon)[grithin](/maintainers/grithin)

---

Top Contributors

[![grithin](https://avatars.githubusercontent.com/u/7241358?v=4)](https://github.com/grithin "grithin (16 commits)")

---

Tags

IoC DI

### Embed Badge

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

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

###  Alternatives

[symfony/dependency-injection

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

4.2k431.1M7.4k](/packages/symfony-dependency-injection)[illuminate/contracts

The Illuminate Contracts package.

704122.9M10.0k](/packages/illuminate-contracts)[illuminate/container

The Illuminate Container package.

31278.1M2.0k](/packages/illuminate-container)[ecotone/ecotone

Supporting you in building DDD, CQRS, Event Sourcing applications with ease.

558549.8k17](/packages/ecotone-ecotone)[civicrm/civicrm-core

Open source constituent relationship management for non-profits, NGOs and advocacy organizations.

728272.9k17](/packages/civicrm-civicrm-core)[internal/dload

Downloads binaries.

98142.7k10](/packages/internal-dload)

PHPackages © 2026

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