PHPackages                             ob-ivan/sd-dependency-injection - 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. ob-ivan/sd-dependency-injection

ActiveLibrary

ob-ivan/sd-dependency-injection
===============================

v1.6(8y ago)01.2k4PHP

Since Jul 31Pushed 8y ago1 watchersCompare

[ Source](https://github.com/ob-ivan/sd-dependency-injection)[ Packagist](https://packagist.org/packages/ob-ivan/sd-dependency-injection)[ RSS](/packages/ob-ivan-sd-dependency-injection/feed)WikiDiscussions master Synced 2mo ago

READMEChangelog (10)Dependencies (1)Versions (13)Used By (4)

Registers services and injects them into consumers.

Installation
============

[](#installation)

```
composer require ob-ivan/sd-dependency-injection
```

Usage
=====

[](#usage)

Terminology
-----------

[](#terminology)

In large applications a situation when some class instances are to be shared among many other classes is common. Think of a database connection instance shared among various controller classes.

Those shared classes are called *services* (they provide some useful functionality to others), and those sharing are called *consumers* (they consume the services provided).

The process of letting a consumer know all services it requires access to is called *injection*.

A consumer may declare formally a list of services it requires. This is called *listing* its *dependencies*. The process of taking a consumer's dependency list and injecting corresponging services into it is called, unsurprisingly, *dependency injection*.

A *dependency injection container* (DIC) is a way to implement dependency injection. It requires that each service is *registered* within the container under a certain *common name*, and that consumers list common names of their required services as formal dependency lists.

Dependecies may be injected into consumers in several different ways. In this library, these three types of dependency injection are supported:

- **Setter injection** aka **Interface injection** - given a consumer Instance implementing DeclarerInterface call a setter for each declared dependency.
- **Constructor injection** - given a consumer's ClassName resolve its constructor arguments as dependency names and call constructor with appropriate services. Setter injection is then invoked on the created instance.
- **Argument injection** - given a consumer Function resolve its arguments as dependency names and call the Function with appropriate services.

You can use a container to register services, or to produce consumers, or to inject dependencies into arbitrary code.

- Consumer = Function | Instance
- ConsumerInitializer = ClassName | Consumer
- ServiceInitializer = ConsumerInitializer | Value

Construction
------------

[](#construction)

A container is initialized with raw values, no Initalizers allowed:

```
$container = new SD\DependencyInjection\Container([
    'name' => 'Chewbaka', // not interpreted as a class name
]);
```

If you have several containers, you can create a new one by merging them:

```
$mergedContainer = SD\DependencyInjection\Container::merge($container1, $container2);
```

Registering services
--------------------

[](#registering-services)

Services are registered with ServiceInitializers:

```
// Setter injection - use when constructing a Service is cheap and doesn't involve resource allocating.
$container->register('helloWorld', new HelloWorldService('Anakin'));

// Constructor injection + Setter injection - use when Service does not require constructor arguments.
$container->register('helloWorld', HelloWorldService::class);

// Argument injection + Setter injection - use when Service requires a constructor argument or
// Service construction is anyhow a complicated process.
$container->register('helloWorld', function ($name) {
    if ($name === strtoupper($name)) {
        return new HelloShouterService($name);
    }
    return new HelloWorldService($name);
});

// No injection - use for setting parameters.
$container->register('name', $container->value('Skywalker'));
```

You do not have to register container within itself, as it is self-aware by default:

```
// The 'container' common name is reserved to refer to the container itself.
$container === $container->get('container');
```

You can extend registered services:

```
// Initial registering:
$container->register('currency', SD\Currency\Repository::class);

// Later on:
$container->extend('currency', function ($container, $currency) {
    $store = $container->produce(SD\CurrencyStore\Wpdb::class);
    $currency->setStore($store);
    return $currency;
});
```

Consumer production
-------------------

[](#consumer-production)

Consumers are produced with ConsumerInitializers (Value is not supported):

```
$controller = $container->produce(HelloWorldController::class);
// or:
$controller = $container->produce(new HelloWorldController('Luke'));
// or:
$controller = $container->produce(function ($catchPhrase) {
    return new HelloWorldController($catchPhrase);
});
```

You can inject services into any Consumer:

```
// Inject into an already instantiated consumer:
$serviceAwareCalculator = $container->inject($serviceUnawareCalculator);

// Inject into a callable:
$response = $container->inject(function ($helloWorldService) use ($name) {
    return $helloWorldService->greet($name);
});
```

Though discouraged, you can use container as service locator, if execution context does not let you use the power of dependency injection:

```
$legacyConsumer = new LegacyConsumer($container->get('brand_new_service'));
```

Defining a consumer
-------------------

[](#defining-a-consumer)

Class consumers (as opposed to callable consumers) declare their dependencies in any of following ways --- or a combination of both:

- By implementing `DeclarerInterface` and returning a list of common names from `declareDependencies`method.
- By implementing `AutoDeclarerInterface` and importing `AutoDeclarerTrait` and `AwareTrait`s of their respective dependencies.

As listing common names in `declareDependencies` method causes heavy reduplication of common names, we recommend to define an `AwareTrait` for each service you define.

Here's a sample code:

```
trait ExampleAwareTrait
{
    // Here's the magic. Create a field named starting with $autoDeclare and containing the service's
    // common name as a value. Don't forget to import AutoDeclarerTrait!
    protected $autoDeclareExample = 'example';
    private $example;

    // Setter name must match the common name.
    public function setExample(ExampleService $example) {
        $this->example = $example;
    }

    // An example way to access an example service instance.
    protected function getExample()
    {
        return $this->example;
    }
}
```

This way defining a consumer in a following way will tell a container to inject ExampleService into it --- or to throw an exception if it's not available.

```
use SD\DependencyInjection\AutoDeclarerInterface;
use SD\DependencyInjection\AutoDeclarerTrait;

class ExampleConsumer implements AutoDeclarerInterface
{
    use AutoDeclarerTrait;
    use ExampleAwareTrait;

    public function run()
    {
        return $this->getExample()->doSomething();
    }
}
```

Service providers
-----------------

[](#service-providers)

You can encapsulate a service's common name further by putting it into a provider.

```
use SD\DependencyInjection\ProviderInterface;

// This provides a correspondence between the service instance and its common name.
class ExampleProvider implements ProviderInterface
{
    public function getServiceName(): string
    {
        return 'example'; // the common name
    }

    public function provide()
    {
        return new ExampleService();
    }
}
```

Then the service is registered with its provider's instance:

```
$container->connect(new ExampleProvider());
```

This way neither registration code nor consumers need to know the common name. They just refer to Provider instance and the AwareTrait, and it just works. Hey, it's magic!

Development
===========

[](#development)

To run tests:

```
composer install
vendor/bin/phpunit
```

###  Health Score

32

—

LowBetter than 72% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity15

Limited adoption so far

Community13

Small or concentrated contributor base

Maturity70

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

Recently: every ~49 days

Total

12

Last Release

3007d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/16bf08194a92f7509a08dfffd03540b37680b368041f74a5c4f82788cace2037?d=identicon)[ob-ivan](/maintainers/ob-ivan)

---

Top Contributors

[![ob-ivan](https://avatars.githubusercontent.com/u/1832804?v=4)](https://github.com/ob-ivan "ob-ivan (3 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/ob-ivan-sd-dependency-injection/health.svg)

```
[![Health](https://phpackages.com/badges/ob-ivan-sd-dependency-injection/health.svg)](https://phpackages.com/packages/ob-ivan-sd-dependency-injection)
```

PHPackages © 2026

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