PHPackages                             rg/injektor - 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. rg/injektor

ActiveLibrary

rg/injektor
===========

Dependency Injection container inspired by google-guice

4.1.1(7mo ago)3973.5k↓31.3%132Apache-2.0PHPPHP &gt;=8.1CI passing

Since Feb 22Pushed 7mo ago10 watchersCompare

[ Source](https://github.com/researchgate/injektor)[ Packagist](https://packagist.org/packages/rg/injektor)[ Docs](http://github.com/researchgate/injektor)[ RSS](/packages/rg-injektor/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (6)Versions (37)Used By (2)

rg\\injektor
============

[](#rginjektor)

rg\\injektor is a sophisticated dependency injection container for PHP that was inspired by Guice. Unlike other reflection based containers rg\\injektor includes a factory class generator that you can use to prevent the use of reflection on production.

[![Test status](https://github.com/researchgate/injektor/actions/workflows/tests.yml/badge.svg)](https://github.com/researchgate/injektor/actions/workflows/tests.yml)

Prerequisites
=============

[](#prerequisites)

This library needs PHP 8.1+.

It has been tested using PHP 8.1 and PHP 8.2.

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

[](#installation)

You can install the library directly with composer. Just run this command in your project directory:

```
$ composer require rg/injektor
```

Usage
=====

[](#usage)

After you installed rg\\injektor you can use it like this:

```
$configuration = new \rg\injektor\Configuration($pathToConfigFile, $pathToFactoryDirectory);
$dic = new \rg\injektor\DependencyInjectionContainer($configuration);

$instance = $dic->getInstanceOfClass('ClassName');
$result = $dic->callMethodOnObject($instance, 'methodName');
```

For more details on the specific features of rg\\injektor see below.

If you use some kind of MVC framework it is recommended to include rg\\injektor in your front controller to create your controller objects and call methods on them.

Generating Factories
====================

[](#generating-factories)

By default rg\\injektor relies heavily on Reflection which is fine for your development environment but would slow down your production environment unnecessarily. So you should use the built in possiblity to use generated factory classes instead. In order to do this you have to generate these factories before deploying your project.

First you have to use the \\rg\\injektor\\FactoryDependencyInjectionContainer class in your code:

```
$configuration = new \rg\injektor\Configuration($pathToConfigFile, $pathToFactoryDirectory);
$dic = new \rg\injektor\FactoryDependencyInjectionContainer($configuration);
```

If no factories are present \\rg\\injektor\\FactoryDependencyInjectionContainer falls back to Reflection.

To generate factories you have to write a small script that iterates over your PHP files and create factories for each of them. Here is an example of such a script based on the Symfony Console Component:

```
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use rg\injektor\WritingFactoryGenerator;

class GenerateDependencyInjectionFactories extends \Symfony\Component\Console\Command\Command
{
    private \rg\injektor\DependencyInjectionContainer $dic;

    private \rg\injektor\WritingFactoryGenerator $factoryGenerator;

    private string $root;

    protected function configure()
    {
        $this->setDescription('generates factories for dependency injection container');
        $this->setHelp('generates factories for dependency injection container');
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $output->writeln('Generating Factories');

        $this->root = '/path/to/your/project';

        $factoryPath = $this->root . '/folder/for/generated/factories';

        if (!file_exists($factoryPath)) {
            mkdir($factoryPath, 0777, true);
        }

        $pathToConfigFile = '/config/dic.php';

        $configuration = new \rg\injektor\Configuration($pathToConfigFile, $factoryPath);
        $this->dic = new \rg\injektor\FactoryDependencyInjectionContainer($configuration);

        $this->factoryGenerator = new WritingFactoryGenerator($this->dic->getConfig(), $factoryPath);

        $this->factoryGenerator->cleanUpGenerationDirectory($factoryPath);

        $this->processAllDirectories($output);
    }

    private function processAllDirectories(OutputInterface $output)
    {
        $this->processDirectory($this->root . DIRECTORY_SEPARATOR . 'folderWithPhpClasses', $output);
    }

    private function processDirectory(string $directory, OutputInterface $output)
    {
        $output->writeln('Directory: ' . $directory);
        $directoryIterator = new \RecursiveDirectoryIterator($directory);
        $iterator = new \RecursiveIteratorIterator($directoryIterator);
        $regexIterator = new \RegexIterator($iterator, '/^.+\.php$/i', \RecursiveRegexIterator::GET_MATCH);
        foreach ($regexIterator as $file) {
            $this->processFile($file[0], $output);
        }
    }

    private function processFile(string $fullpath, OutputInterface $output)
    {
        $output->writeln('Process file [' . $fullpath . ']');

        require_once $fullpath;

        $astLocator = (new \Roave\BetterReflection\BetterReflection())->astLocator();

        $reflector  = new \Roave\BetterReflection\Reflector\DefaultReflector(new Roave\BetterReflection\SourceLocator\Type\SingleFileSourceLocator($fileName, $astLocator));
        $classes = $reflector->reflectAllClasses();

        foreach ($classes as $class) {
            $generator->processClass($class->getName());
        }
    }

    private function processClass(\Laminas\Code\Reflection\ClassReflection $class)
    {
        if (!$class->isInstantiable()) {
            return;
        }
        $this->factoryGenerator->processFileForClass($class->name);
    }
}
```

Features
========

[](#features)

Constructor Injection
---------------------

[](#constructor-injection)

```
use rg\injektor\attributes\Inject;

class Foo
{
    #[Inject]
    public function __construct(Bar $bar)
    {

    }
}

class Bar
{

}

$dic->getInstanceOfClass('Foo');
```

An instance of Bar will be injected as the constructor argument $bar. Of course Bar could use dependency injection as well. The container can inject any classes that are injectable because:

- they have a @inject annotation or `rg\injektor\attributes\Inject` attribute at the constructor
- they have a constructor without arguments
- they have no constructor
- the arguments are optional
- the arguments are configured (see below)

A constructor can be either a \_\_construct method or a static getInstance method if the class is configured as singleton and the \_\_construct method is private or protected.

```
use rg\injektor\attributes\Inject;
use rg\injektor\attributes\Singleton;

class Foo
{
    #[Inject]
    public function __construct(Bar $bar)
    {

    }
}

 #[Singleton]
class Bar
{
    private function __construct()
    {

    }

    public static function getInstance()
    {

    }
}

$dic->getInstanceOfClass('Foo');
```

Property Injection
------------------

[](#property-injection)

```
use rg\injektor\attributes\Inject;

class Foo
{
    #[Inject]
    protected Bar $bar;
}

class Bar
{

}

$dic->getInstanceOfClass('Foo');
```

Field $bar will have an instance of Bar. In order for this to work the field can not be private but has to be protected or public. This can also be combined with constructor injection.

Inject Concrete Implementation
------------------------------

[](#inject-concrete-implementation)

```
use rg\injektor\attributes\Inject;
use rg\injektor\attributes\ImplementedBy;

class Foo
{
    #[Inject]
    protected Bar $bar;
}

 #[ImplementedBy(className: BarImpl::class)]
interface Bar
{

}

class BarImpl implements Bar
{

}

$dic->getInstanceOfClass('Foo');
```

Instead of Bar, BarImpl is injected into $bar. You can also configure this in the dependecy injection configuration instead of using annotations

```
'Bar' => array(
    'class' => 'BarImpl'
)
```

Using Provider Classes
----------------------

[](#using-provider-classes)

```
use rg\injektor\attributes\Inject;
use rg\injektor\attributes\ProvidedBy;

class Foo
{
    #[Inject]
    protected Bar $bar;
}

 #[ProvidedBy(className: BarProvider::class)]
interface Bar
{

}

class BarImpl implements Bar
{

}

class BarProvider implements rg\injektor\Provider
{
    public function get()
    {
        return new BarImpl();
    }
}

$dic->getInstanceOfClass('Foo');
```

Instead of Bar, the return value of BarProvider's get Method (BarImpl) is injected into $bar. You can also configure this in the dependecy injection configuration instead of using annotations

```
'Bar' => array(
    'provider' => array(
        'class' => 'BarImpl'
    )
)
```

Passing fixed data to providers
-------------------------------

[](#passing-fixed-data-to-providers)

```
use rg\injektor\attributes\Inject;
use rg\injektor\attributes\ProvidedBy;
use rg\injektor\attributes\Param;

class Foo
{
    #[Inject]
    protected Bar $bar;
}

#[ProvidedBy(className: BarProvider::class, overwriteParams: [new Param('foo', 'bar')])]
interface Bar
{

}

class BarImpl implements Bar
{

}

class BarProvider implements rg\injektor\Provider
{

    #[Inject]
    public function __construct(SomeClass $someClass, $foo)
    {
    }

    public function get()
    {
        return new BarImpl();
    }
}

$dic->getInstanceOfClass('Foo');
```

Here the provider gets an additional instance of SomeClass injected. The variable $foo is set to 'bar'. You can also configure this in the config:

```
'Bar' => array(
    'provider' => array(
        'class' => 'BarImpl',
        'params' => array(
            'foo' => 'bar',
        )
    )
)
```

Inject as Singleton
-------------------

[](#inject-as-singleton)

```
use rg\injektor\attributes\Inject;
use rg\injektor\attributes\Singleton;

class Foo
{
    #[Inject]
    protected Bar $bar;
}

#[Singleton]
class Bar
{

}

$instanceOne = $dic->getInstanceOfClass('Foo');
$instanceTwo = $dic->getInstanceOfClass('Foo');
```

Both $instanceOne and $instanceTwo will have the same instance of Bar injections.

You can also configure this in the dependecy injection configuration instead of using annotations

```
'Bar' => array(
    'singleton' => true
)
```

Note that for a singleton injektor analizes the given arguments of the injected class to determine if the wanted instance is already created or not.

That means in this example:

```
use rg\injektor\attributes\Inject;
use rg\injektor\attributes\Singleton;

class Foo
{
    #[Inject]
    protected Bar $bar;
}

#[Singleton]
class Bar
{
    public function __construct($arg)
    {
    }
}

$instanceOne = $dic->getInstanceOfClass('Foo', array('arg' => 1));
$instanceTwo = $dic->getInstanceOfClass('Foo', array('arg' => 2));
```

$instanceOne and $instanceTwo will be different instances. This feature comes with a speed price though, so if you want to have the same instance regardless of the parameter are always pass in the same or inject all parameters, mark it as a service instead (see below).

Injecting as service
--------------------

[](#injecting-as-service)

```
use rg\injektor\attributes\Inject;
use rg\injektor\attributes\Singleton;

class Foo
{
    #[Inject]
    protected Bar $bar;
}

#[Service]
class Bar
{

}

$instanceOne = $dic->getInstanceOfClass('Foo');
$instanceTwo = $dic->getInstanceOfClass('Foo');
```

Both $instanceOne and $instanceTwo will have the same instance of Bar injections.

You can also configure this in the dependecy injection configuration instead of using annotations

```
'Bar' => array(
    'service' => true
)
```

In contrast to singletons, In a service this example

```
use rg\injektor\attributes\Inject;
use rg\injektor\attributes\Service;

class Foo
{
    #[Inject]
    protected Bar $bar;
}

#[Service]
class Bar
{
    public function __construct($arg)
    {
    }
}

$instanceOne = $dic->getInstanceOfClass('Foo', array('arg' => 1));
$instanceTwo = $dic->getInstanceOfClass('Foo', array('arg' => 2));
```

would lead to $instanceOne and $instanceTwo being the same object instance.

Configuring parameters
----------------------

[](#configuring-parameters)

You can also configure the content of all or some parameters that the container should pass to the \_\_construct or getInstance method in the configuration instead of letting the container guess them from typehints:

```
use rg\injektor\attributes\Inject;
use rg\injektor\attributes\Singleton;

class Foo
{
    #[Inject]
    public function __construct($bar)
    {

    }
}

#[Singleton]
class Bar
{
    private function __construct()
    {

    }

    #[Inject]
    public static function getInstance($foo, $buzz)
    {

    }
}

$dic->getInstanceOfClass('Foo');
```

Configuration:

```
'Foo' => array(
    'params' => array(
        'bar' => array(
            'class' => 'Bar'
        )
    )
),
'Bar' = array(
    'params' => array(
        'foo' => array(
            'value' => 'fooBar'
        ),
        'buzz' => array(
            'value' => true
        )
    )
)
```

Alternatively you can also configure this with annotations

```
use rg\injektor\attributes\Inject;
use rg\injektor\attributes\Singleton;
use rg\injektor\attributes\Param;

class Foo
{
     #[Inject(overwriteParams: [
        new Param('foo', 456),
        new Param('buzz', 'content')
     ])]
    protected Bar $propertyInjection;

    public function __construct(
        #[Inject(overwriteParams: [)]
            new Param('foo', 123),
            new Param('buzz', 'content')
        ])]
        Bar $bar
    ) {

    }
}

#[Singleton]
class Bar
{
    private function __construct()
    {

    }

    #[Inject]
    public static function getInstance($foo, $buzz)
    {

    }
}

$dic->getInstanceOfClass('Foo');
```

Pass additional parameters on runtime
-------------------------------------

[](#pass-additional-parameters-on-runtime)

You also can pass some values to the new instance on runtime.

```
use rg\injektor\attributes\Inject;

class Foo
{
    #[Inject]
    public function __construct($val, Bar $bar, Buzz $buzz)
    {

    }
}

class Bar
{
}

class Buzz
{
}

$dic->getInstanceOfClass('Foo', array(
    'val' => 123,
    'buzz' => new Buzz()
));
```

This can also be combined with configured parameters.

Named injection
---------------

[](#named-injection)

```
use rg\injektor\attributes\Inject;

class Foo
{
    #[Inject(named: 'barOne')]
    protected Bar $bar;

    #[Inject]
    public function __construct(
        #[Inject(named: 'barOne')]
        Bar $one,
        #[Inject(named: 'barTwo')]
        Bar $two,
        // default implementation, requires #[Inject] on the constructor level
        Bar $default,
        #[Inject] // works the same as above, but doesn't require #[Inject] on the constructor level
        Bar $default2,
    ) {

    }
}

interface Bar
{

}

class BarImplDefault implements Bar
{

}

class BarImplOne implements Bar
{

}

class BarImplTwo implements Bar
{

}

$dic->getInstanceOfClass('Foo');
```

Configuration:

```
'Bar' => array(
    'class' => 'BarImplDefault'
    'named' => array(
        'barOne' => 'BarImplOne',
        'barTwo' => 'BarImplTwo'
    )
)
```

You can also configure this directly with annotations

```
use rg\injektor\attributes\ImplementedBy;

#[ImplementedBy(className: BarImplDefault::class)]
#[ImplementedBy(className: BarImplOne::class, named: 'barOne')]
#[ImplementedBy(className: BarImplTwo::class, named: 'barTwo')]
interface Bar
{

}

class BarImplDefault implements Bar
{

}

class BarImplOne implements Bar
{

}

class BarImplTwo implements Bar
{

}
```

It is also possible to name the default implementation, so that our configuration looks a bit cleaner. The result is the same:

```
use rg\injektor\attributes\ImplementedBy;

#[ImplementedBy(BarImplDefault::class)]
#[ImplementedBy(className: BarImplOne::class, named: 'barOne')]
#[ImplementedBy(className: BarImplTwo::class, named: 'barTwo')]
interface Bar
{

}
```

Named providers
---------------

[](#named-providers)

```
use rg\injektor\attributes\Inject;

class Foo
{
    #[Inject(named: 'barOne')]
    protected Bar $bar;

    #[Inject]
    public function __construct(
        #[Inject(named: 'barOne')]
        Bar $one,
        #[Inject(named: 'barTwo')]
        Bar $two,
        Bar $default,
    ) {
    }
}

interface Bar
{

}

$dic->getInstanceOfClass('Foo');
```

Configuration:

```
'Bar' => array(
    'provider' => array(
        'class' => 'BarProvider'
    ),
    'namedProviders' => array(
        'barOne' => array(
            'class' => 'BarProvider',
            'parameters' => array('name' => 'barOne')
        ),
        'barTwo' => array(
            'class' => 'BarProvider',
            'parameters' => array('name' => 'barTwo')
        )
    )
)
```

You can also configure this directly with annotations

```
use rg\injektor\attributes\ProvidedBy;
use rg\injektor\attributes\Param;

#[ProvidedBy(BarProvider::class)]
#[ProvidedBy(BarProvider::class, named: 'barOne', overwriteParams: [new Param('name', 'barOne')])]
#[ProvidedBy(BarProvider::class, named: 'barTwo', overwriteParams: [new Param('name', 'barTwo')])]
interface Bar
{

}

class BarProvider implements rg\injektor\Provider
{
    private $name;

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

    public function get()
    {
        switch ($this->name) {
            case 'barOne':
                return new BarImplOne();
            case 'barTwo':
                return new BarImplTwo();
        }

        return new BarImplDefault();
    }
}

class BarImplDefault implements Bar
{

}

class BarImplOne implements Bar
{

}

class BarImplTwo implements Bar
{

}
```

It is also possible to name the default provider, so that our configuration looks a bit cleaner. The result is the same:

```
use rg\injektor\attributes\ProvidedBy;
use rg\injektor\attributes\Param;

#[ProvidedBy(BarProvider::class, named: 'default')]
#[ProvidedBy(BarProvider::class, named: 'barOne', overwriteParams: [new Param('name', 'barOne')])]
#[ProvidedBy(BarProvider::class, named: 'barTwo', overwriteParams: [new Param('name', 'barTwo')])]
interface Bar
{

}
```

Call method on object instance
------------------------------

[](#call-method-on-object-instance)

The container can also call methods on instances an inject all method arguments

```
use rg\injektor\attributes\Inject;

class Foo
{
    #[Inject]
    public function doSomething(Bar $bar)
    {
    }
}

class Bar
{

}

$foo = new Foo();
$dic->callMethodOnObject($foo, 'doSomething');
```

Of course you can also use named injections.

It is also possible to add additional values to the method call, like with object creation:

```
use rg\injektor\attributes\Inject;

class Foo
{
    #[Inject]
    public function doSomething(Bar $bar, $foo)
    {
    }
}

class Bar
{

}

$foo = new Foo();
$dic->callMethodOnObject($foo, 'doSomething', array('foo' => 'value'));
```

###  Health Score

58

—

FairBetter than 98% of packages

Maintenance64

Regular maintenance activity

Popularity42

Moderate usage in the ecosystem

Community30

Small or concentrated contributor base

Maturity84

Battle-tested with a long release history

 Bus Factor2

2 contributors hold 50%+ of commits

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

Recently: every ~182 days

Total

33

Last Release

221d ago

Major Versions

1.6.0 → 2.0.02020-07-06

2.2.0 → 3.0.02022-05-10

3.1.4 → 4.0.02024-01-08

PHP version history (9 changes)v1.0.0PHP &gt;=5.3.2

1.3.5PHP &gt;=5.4.0

1.3.6PHP &gt;=5.5.0

1.4.0PHP &gt;=7.1.0

1.5.0PHP &gt;=7.2.0

2.0.1PHP ^7.2

3.0.0PHP ^7.4 || ^8.0

3.1.0PHP &gt;=8.0

4.0.0PHP &gt;=8.1

### Community

Maintainers

![](https://www.gravatar.com/avatar/3339a5bc868a2844d31d1f9941062702bb1f6e0324964e8bc5154200bc59af3e?d=identicon)[mdio](/maintainers/mdio)

![](https://www.gravatar.com/avatar/bc721d458daef6acfa87d9a3106f9c615e2aae77348d644af4270693e8c23dad?d=identicon)[grid\_rg](/maintainers/grid_rg)

---

Top Contributors

[![bashofmann](https://avatars.githubusercontent.com/u/243056?v=4)](https://github.com/bashofmann "bashofmann (69 commits)")[![danez](https://avatars.githubusercontent.com/u/231804?v=4)](https://github.com/danez "danez (24 commits)")[![mdio](https://avatars.githubusercontent.com/u/8616698?v=4)](https://github.com/mdio "mdio (23 commits)")[![rg-scheb](https://avatars.githubusercontent.com/u/249925692?v=4)](https://github.com/rg-scheb "rg-scheb (11 commits)")[![rtens](https://avatars.githubusercontent.com/u/1468866?v=4)](https://github.com/rtens "rtens (4 commits)")[![edorian](https://avatars.githubusercontent.com/u/247397?v=4)](https://github.com/edorian "edorian (3 commits)")[![mustafah15](https://avatars.githubusercontent.com/u/6823250?v=4)](https://github.com/mustafah15 "mustafah15 (3 commits)")[![scheb](https://avatars.githubusercontent.com/u/1259952?v=4)](https://github.com/scheb "scheb (2 commits)")[![woodworker](https://avatars.githubusercontent.com/u/85796?v=4)](https://github.com/woodworker "woodworker (2 commits)")[![nawarian](https://avatars.githubusercontent.com/u/3905582?v=4)](https://github.com/nawarian "nawarian (1 commits)")[![htimur](https://avatars.githubusercontent.com/u/575813?v=4)](https://github.com/htimur "htimur (1 commits)")[![manuelpichler](https://avatars.githubusercontent.com/u/58714?v=4)](https://github.com/manuelpichler "manuelpichler (1 commits)")[![Darijusch](https://avatars.githubusercontent.com/u/1653245?v=4)](https://github.com/Darijusch "Darijusch (1 commits)")[![edlerd](https://avatars.githubusercontent.com/u/1155472?v=4)](https://github.com/edlerd "edlerd (1 commits)")[![olexiyk](https://avatars.githubusercontent.com/u/1378579?v=4)](https://github.com/olexiyk "olexiyk (1 commits)")

---

Tags

dependencyinjection

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/rg-injektor/health.svg)

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

###  Alternatives

[league/container

A fast and intuitive dependency injection container.

86787.8M343](/packages/league-container)[php-di/invoker

Generic and extensible callable invoker

26857.8M56](/packages/php-di-invoker)[neos/flow

Flow Application Framework

862.0M451](/packages/neos-flow)[neos/flow-development-collection

Flow packages in a joined repository for pull requests.

144179.3k3](/packages/neos-flow-development-collection)[yiisoft/di

Yii DI container

2351.2M100](/packages/yiisoft-di)[reinfi/zf-dependency-injection

A Laminas Framework module for loading dependencies via annotation or config entries.

21115.4k1](/packages/reinfi-zf-dependency-injection)

PHPackages © 2026

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