{"id":19028681,"url":"https://github.com/researchgate/injektor","last_synced_at":"2025-05-08T23:45:26.754Z","repository":{"id":3234004,"uuid":"4270154","full_name":"researchgate/injektor","owner":"researchgate","description":"Dependency injection container for PHP, inspired by google-guice","archived":false,"fork":false,"pushed_at":"2024-04-24T12:29:00.000Z","size":279,"stargazers_count":38,"open_issues_count":0,"forks_count":13,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-05-08T23:45:18.806Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/researchgate.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2012-05-09T09:26:37.000Z","updated_at":"2023-10-15T07:06:53.000Z","dependencies_parsed_at":"2023-10-10T17:23:48.437Z","dependency_job_id":"a762338e-d3dd-45c4-b48c-1f4c667a7b29","html_url":"https://github.com/researchgate/injektor","commit_stats":{"total_commits":141,"total_committers":18,"mean_commits":7.833333333333333,"dds":0.6028368794326241,"last_synced_commit":"d1cece345e9b28e3434c3b4e4a19c98a271cf45b"},"previous_names":[],"tags_count":32,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/researchgate%2Finjektor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/researchgate%2Finjektor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/researchgate%2Finjektor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/researchgate%2Finjektor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/researchgate","download_url":"https://codeload.github.com/researchgate/injektor/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253166474,"owners_count":21864467,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-08T21:12:01.052Z","updated_at":"2025-05-08T23:45:26.729Z","avatar_url":"https://github.com/researchgate.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# rg\\\\injektor\n\nrg\\\\injektor is a sophisticated dependency injection container for PHP that was inspired by Guice.\nUnlike other reflection based containers rg\\\\injektor includes a factory class generator that you can use to prevent\nthe use of reflection on production.\n\n[![Test status](https://github.com/researchgate/injektor/actions/workflows/tests.yml/badge.svg)](https://github.com/researchgate/injektor/actions/workflows/tests.yml)\n\n# Prerequisites\n\nThis library needs PHP 8.1+.\n\nIt has been tested using PHP 8.1 and PHP 8.2.\n\n\n# Installation\n\nYou can install the library directly with composer. Just run this command in your project directory:\n```bash\n$ composer require rg/injektor\n```\n\n# Usage\nAfter you installed rg\\\\injektor you can use it like this:\n\n```php\n$configuration = new \\rg\\injektor\\Configuration($pathToConfigFile, $pathToFactoryDirectory);\n$dic = new \\rg\\injektor\\DependencyInjectionContainer($configuration);\n\n$instance = $dic-\u003egetInstanceOfClass('ClassName');\n$result = $dic-\u003ecallMethodOnObject($instance, 'methodName');\n```\n\nFor more details on the specific features of rg\\\\injektor see below.\n\nIf you use some kind of MVC framework it is recommended to include rg\\\\injektor in your front controller to create\nyour controller objects and call methods on them.\n\n# Generating Factories\n\nBy default rg\\\\injektor relies heavily on Reflection which is fine for your development environment but would slow down\nyour production environment unnecessarily. So you should use the built in possiblity to use generated factory classes\ninstead. In order to do this you have to generate these factories before deploying your project.\n\nFirst you have to use the \\rg\\injektor\\FactoryDependencyInjectionContainer class in your code:\n\n```php\n$configuration = new \\rg\\injektor\\Configuration($pathToConfigFile, $pathToFactoryDirectory);\n$dic = new \\rg\\injektor\\FactoryDependencyInjectionContainer($configuration);\n```\nIf no factories are present \\rg\\injektor\\FactoryDependencyInjectionContainer falls back to Reflection.\n\nTo generate factories you have to write a small script that iterates over your PHP files and create factories for each\nof them. Here is an example of such a script based on the Symfony Console Component:\n\n```php\nuse Symfony\\Component\\Console\\Input\\InputInterface;\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\nuse rg\\injektor\\WritingFactoryGenerator;\n\nclass GenerateDependencyInjectionFactories extends \\Symfony\\Component\\Console\\Command\\Command\n{\n    /**\n     * @var \\rg\\injektor\\DependencyInjectionContainer\n     */\n    private $dic;\n\n    /**\n     * @var \\rg\\injektor\\WritingFactoryGenerator\n     */\n    private $factoryGenerator;\n\n    /**\n     * @var string\n     */\n    private $root;\n\n    protected function configure()\n    {\n        $this-\u003esetDescription('generates factories for dependency injection container');\n        $this-\u003esetHelp('generates factories for dependency injection container');\n    }\n\n    /**\n     * @param InputInterface $input\n     * @param OutputInterface $output\n     */\n    protected function execute(InputInterface $input, OutputInterface $output)\n    {\n        $output-\u003ewriteln('Generating Factories');\n\n        $this-\u003eroot = '/path/to/your/project';\n\n        $factoryPath = $this-\u003eroot . '/folder/for/generated/factories';\n\n        if (!file_exists($factoryPath)) {\n            mkdir($factoryPath, 0777, true);\n        }\n\n        $pathToConfigFile = '/config/dic.php';\n\n        $configuration = new \\rg\\injektor\\Configuration($pathToConfigFile, $factoryPath);\n        $this-\u003edic = new \\rg\\injektor\\FactoryDependencyInjectionContainer($configuration);\n\n        $this-\u003efactoryGenerator = new WritingFactoryGenerator($this-\u003edic-\u003egetConfig(), $factoryPath);\n\n        $this-\u003efactoryGenerator-\u003ecleanUpGenerationDirectory($factoryPath);\n\n        $this-\u003eprocessAllDirectories($output);\n    }\n\n    /**\n     * @param OutputInterface $output\n     */\n    private function processAllDirectories(OutputInterface $output)\n    {\n        $this-\u003eprocessDirectory($this-\u003eroot . DIRECTORY_SEPARATOR . 'folderWithPhpClasses', $output);\n    }\n\n    /**\n     * @param $directory\n     * @param OutputInterface $output\n     */\n    private function processDirectory($directory, OutputInterface $output)\n    {\n        $output-\u003ewriteln('Directory: ' . $directory);\n        $directoryIterator = new \\RecursiveDirectoryIterator($directory);\n        $iterator = new \\RecursiveIteratorIterator($directoryIterator);\n        $regexIterator = new \\RegexIterator($iterator, '/^.+\\.php$/i', \\RecursiveRegexIterator::GET_MATCH);\n        foreach ($regexIterator as $file) {\n            $this-\u003eprocessFile($file[0], $output);\n        }\n    }\n\n    /**\n     * @param $fullpath\n     * @param OutputInterface $output\n     */\n    private function processFile($fullpath, OutputInterface $output)\n    {\n        $output-\u003ewriteln('Process file [' . $fullpath . ']');\n\n        require_once $fullpath;\n\n        $astLocator = (new \\Roave\\BetterReflection\\BetterReflection())-\u003eastLocator();\n\n        $reflector  = new \\Roave\\BetterReflection\\Reflector\\DefaultReflector(new Roave\\BetterReflection\\SourceLocator\\Type\\SingleFileSourceLocator($fileName, $astLocator));\n        $classes = $reflector-\u003ereflectAllClasses();\n\n        foreach ($classes as $class) {\n            $generator-\u003eprocessClass($class-\u003egetName());\n        }\n    }\n\n    /**\n     * @param \\Laminas\\Code\\Reflection\\ClassReflection $class\n     */\n    private function processClass(\\Laminas\\Code\\Reflection\\ClassReflection $class)\n    {\n        if (!$class-\u003eisInstantiable()) {\n            return;\n        }\n        $this-\u003efactoryGenerator-\u003eprocessFileForClass($class-\u003ename);\n    }\n}\n```\n\n# Features\n\nConstructor Injection\n---------------------\n\n```php\nclass Foo\n{\n    /**\n     * @inject\n     * @param Bar $bar\n     */\n    public function __construct(Bar $bar)\n    {\n\n    }\n}\n\nclass Bar\n{\n\n}\n\n$dic-\u003egetInstanceOfClass('Foo');\n```\n\nAn instance of Bar will be injected as the constructor argument $bar. Of course Bar could use dependency injection as\nwell. The container can inject any classes that are injectable because:\n\n- they have a @inject annotation at the constructor\n- they have a constructor without arguments\n- they have no constructor\n- the arguments are optional\n- the arguments are configured (see below)\n\nA constructor can be either a __construct method or a static getInstance method if the class is configured as singleton\nand the __construct method is private or protected.\n\n```php\nclass Foo\n{\n    /**\n     * @inject\n     * @param Bar $bar\n     */\n    public function __construct(Bar $bar)\n    {\n\n    }\n}\n\n/**\n * @singleton\n */\nclass Bar\n{\n    private function __construct()\n    {\n\n    }\n\n    public static function getInstance()\n    {\n\n    }\n}\n\n$dic-\u003egetInstanceOfClass('Foo');\n```\n\nProperty Injection\n------------------\n\n```php\nclass Foo\n{\n    /**\n     * @inject\n     * @var Bar\n     */\n    protected $bar;\n}\n\nclass Bar\n{\n\n}\n\n$dic-\u003egetInstanceOfClass('Foo');\n```\n\nField $bar will have an instance of Bar. In order for this to work the field can not be private but has to be protected\nor public. This can also be combined with constructor injection.\n\nInject Concrete Implementation\n------------------------------\n\n```php\nclass Foo\n{\n    /**\n     * @inject\n     * @var Bar\n     */\n    protected $bar;\n}\n\n/**\n * @implementedBy BarImpl\n */\ninterface Bar\n{\n\n}\n\nclass BarImpl implements Bar\n{\n\n}\n\n$dic-\u003egetInstanceOfClass('Foo');\n```\n\nInstead of Bar, BarImpl is injected into $bar. You can also configure this in the dependecy injection configuration\ninstead of using annotations\n\n```php\n'Bar' =\u003e array(\n    'class' =\u003e 'BarImpl'\n)\n```\n\nUsing Provider Classes\n----------------------\n\n```php\nclass Foo\n{\n    /**\n     * @inject\n     * @var Bar\n     */\n    protected $bar;\n}\n\n/**\n * @providedBy BarProvider\n */\ninterface Bar\n{\n\n}\n\nclass BarImpl implements Bar\n{\n\n}\n\nclass BarProvider implements rg\\injektor\\Provider\n{\n    public function get()\n    {\n        return new BarImpl();\n    }\n}\n\n$dic-\u003egetInstanceOfClass('Foo');\n```\n\nInstead of Bar, the return value of BarProvider's get Method (BarImpl) is injected into $bar. You can also\nconfigure this in the dependecy injection configuration instead of using annotations\n\n```php\n'Bar' =\u003e array(\n    'provider' =\u003e array(\n        'class' =\u003e 'BarImpl'\n    )\n)\n```\n\nPassing fixed data to providers\n-------------------------------\n\n```php\nclass Foo\n{\n    /**\n     * @inject\n     * @var Bar\n     */\n    protected $bar;\n}\n\n/**\n * @providedBy BarProvider {'foo' : 'bar'}\n */\ninterface Bar\n{\n\n}\n\nclass BarImpl implements Bar\n{\n\n}\n\nclass BarProvider implements rg\\injektor\\Provider\n{\n\n    /**\n     * @inject\n     */\n    public function __construct(SomeClass $someClass, $foo)\n    {\n    }\n\n    public function get()\n    {\n        return new BarImpl();\n    }\n}\n\n$dic-\u003egetInstanceOfClass('Foo');\n```\n\nHere the provider gets an additional instance of SomeClass injected. The variable $foo is set to 'bar'. You can also\nconfigure this in the config:\n\n```php\n'Bar' =\u003e array(\n    'provider' =\u003e array(\n        'class' =\u003e 'BarImpl',\n        'params' =\u003e array(\n            'foo' =\u003e 'bar',\n        )\n    )\n)\n```\n\n\n\nInject as Singleton\n-------------------\n\n```php\nclass Foo\n{\n    /**\n     * @inject\n     * @var Bar\n     */\n    protected $bar;\n}\n\n/**\n * @singleton\n */\nclass Bar\n{\n\n}\n\n$instanceOne = $dic-\u003egetInstanceOfClass('Foo');\n$instanceTwo = $dic-\u003egetInstanceOfClass('Foo');\n```\n\nBoth $instanceOne and $instanceTwo will have the same instance of Bar injections.\n\nYou can also configure this in the dependecy injection configuration instead of using annotations\n\n```php\n'Bar' =\u003e array(\n    'singleton' =\u003e true\n)\n```\n\nNote that for a singleton injektor analizes the given arguments of the injected class to determine if\nthe wanted instance is already created or not.\n\nThat means in this example:\n\n```php\nclass Foo\n{\n    /**\n     * @inject\n     * @var Bar\n     */\n    protected $bar;\n}\n\n/**\n * @singleton\n */\nclass Bar\n{\n    public function __construct($arg)\n    {\n    }\n}\n\n$instanceOne = $dic-\u003egetInstanceOfClass('Foo', array('arg' =\u003e 1));\n$instanceTwo = $dic-\u003egetInstanceOfClass('Foo', array('arg' =\u003e 2));\n```\n\n$instanceOne and $instanceTwo will be different instances. This feature comes with a speed price though,\nso if you want to have the same instance regardless of the parameter are always pass in the same or\ninject all parameters, mark it as a service instead (see below).\n\nInjecting as service\n--------------------\n\n```php\nclass Foo\n{\n    /**\n     * @inject\n     * @var Bar\n     */\n    protected $bar;\n}\n\n/**\n * @service\n */\nclass Bar\n{\n\n}\n\n$instanceOne = $dic-\u003egetInstanceOfClass('Foo');\n$instanceTwo = $dic-\u003egetInstanceOfClass('Foo');\n```\n\nBoth $instanceOne and $instanceTwo will have the same instance of Bar injections.\n\nYou can also configure this in the dependecy injection configuration instead of using annotations\n\n```php\n'Bar' =\u003e array(\n    'service' =\u003e true\n)\n```\n\nIn contrast to singletons, In a service this example\n\n```php\nclass Foo\n{\n    /**\n     * @inject\n     * @var Bar\n     */\n    protected $bar;\n}\n\n/**\n * @service\n */\nclass Bar\n{\n    public function __construct($arg)\n    {\n    }\n}\n\n$instanceOne = $dic-\u003egetInstanceOfClass('Foo', array('arg' =\u003e 1));\n$instanceTwo = $dic-\u003egetInstanceOfClass('Foo', array('arg' =\u003e 2));\n```\n\nwould lead to $instanceOne and $instanceTwo being the same object instance.\n\nConfiguring parameters\n----------------------\n\nYou can also configure the content of all or some parameters that the container should pass to the __construct or getInstance\nmethod in the configuration instead of letting the container guess them from typehints:\n\n```php\nclass Foo\n{\n    /**\n     * @inject\n     */\n    public function __construct($bar)\n    {\n\n    }\n}\n\n/**\n * @singleton\n */\nclass Bar\n{\n    private function __construct()\n    {\n\n    }\n\n    /**\n     * @inject\n     */\n    public static function getInstance($foo, $buzz)\n    {\n\n    }\n}\n\n$dic-\u003egetInstanceOfClass('Foo');\n```\n\nConfiguration:\n\n```php\n'Foo' =\u003e array(\n    'params' =\u003e array(\n        'bar' =\u003e array(\n            'class' =\u003e 'Bar'\n        )\n    )\n),\n'Bar' = array(\n    'params' =\u003e array(\n        'foo' =\u003e array(\n            'value' =\u003e 'fooBar'\n        ),\n        'buzz' =\u003e array(\n            'value' =\u003e true\n        )\n    )\n)\n```\n\nAlternatively you can also configure this with annotations\n\n```php\nclass Foo\n{\n    /**\n     * @inject\n     * @var Bar {\"foo\":456,\"buzz\":\"content\"}\n     */\n    protected $propertyInjection;\n\n\n    /**\n     * @inject\n     * @param Bar $bar {\"foo\":123,\"buzz\":\"content\"}\n     */\n    public function __construct(Bar $bar)\n    {\n\n    }\n}\n\n/**\n * @singleton\n */\nclass Bar\n{\n    private function __construct()\n    {\n\n    }\n\n    /**\n     * @inject\n     */\n    public static function getInstance($foo, $buzz)\n    {\n\n    }\n}\n\n$dic-\u003egetInstanceOfClass('Foo');\n```\n\nPass additional parameters on runtime\n-------------------------------------\n\nYou also can pass some values to the new instance on runtime.\n\n```php\nclass Foo\n{\n    /**\n     * @inject\n     */\n    public function __construct($val, Bar $bar, Buzz $buzz)\n    {\n\n    }\n}\n\nclass Bar\n{\n}\n\nclass Buzz\n{\n}\n\n$dic-\u003egetInstanceOfClass('Foo', array(\n    'val' =\u003e 123,\n    'buzz' =\u003e new Buzz()\n));\n```\n\nThis can also be combined with configured parameters.\n\nNamed injection\n---------------\n\n```php\nclass Foo\n{\n    /**\n     * @var Bar\n     * @named barOne\n     */\n    protected $bar;\n\n    /**\n     * @inject\n     * @param Bar $one\n     * @param Bar $two\n     * @param Bar $default\n     * @named barOne $one\n     * @named barTwo $two\n     */\n    public function __construct(Bar $one, Bar $two, Bar $default)\n    {\n\n    }\n}\n\ninterface Bar\n{\n\n}\n\nclass BarImplDefault implements Bar\n{\n\n}\n\nclass BarImplOne implements Bar\n{\n\n}\n\nclass BarImplTwo implements Bar\n{\n\n}\n\n$dic-\u003egetInstanceOfClass('Foo');\n```\n\nConfiguration:\n\n```php\n'Bar' =\u003e array(\n    'class' =\u003e 'BarImplDefault'\n    'named' =\u003e array(\n        'barOne' =\u003e 'BarImplOne',\n        'barTwo' =\u003e 'BarImplTwo'\n    )\n)\n```\n\nYou can also configure this directly with annotations\n\n```php\n/**\n * @implementedBy BarImplDefault\n * @implementedBy barOne BarImplOne\n * @implementedBy barTwo BarImplTwo\n */\ninterface Bar\n{\n\n}\n\nclass BarImplDefault implements Bar\n{\n\n}\n\nclass BarImplOne implements Bar\n{\n\n}\n\nclass BarImplTwo implements Bar\n{\n\n}\n```\n\nIt is also possible to name the default implementation, so that our configuration looks a bit cleaner. The result is the\nsame:\n\n```php\n/**\n * @implementedBy default BarImplDefault\n * @implementedBy barOne  BarImplOne\n * @implementedBy barTwo  BarImplTwo\n */\ninterface Bar\n{\n\n}\n```\n\nNamed providers\n---------------\n\n```php\nclass Foo\n{\n    /**\n     * @var Bar\n     * @named barOne\n     */\n    protected $bar;\n\n    /**\n     * @inject\n     * @param Bar $one\n     * @param Bar $two\n     * @param Bar $default\n     * @named barOne $one\n     * @named barTwo $two\n     */\n    public function __construct(Bar $one, Bar $two, Bar $default)\n    {\n    }\n}\n\ninterface Bar\n{\n\n}\n\n$dic-\u003egetInstanceOfClass('Foo');\n```\n\nConfiguration:\n\n```php\n'Bar' =\u003e array(\n    'provider' =\u003e array(\n        'class' =\u003e 'BarProvider'\n    ),\n    'namedProviders' =\u003e array(\n        'barOne' =\u003e array(\n            'class' =\u003e 'BarProvider',\n            'parameters' =\u003e array('name' =\u003e 'barOne')\n        ),\n        'barTwo' =\u003e array(\n            'class' =\u003e 'BarProvider',\n            'parameters' =\u003e array('name' =\u003e 'barTwo')\n        )\n    )\n)\n```\n\nYou can also configure this directly with annotations\n\n```php\n/**\n * @providedBy BarProvider\n * @providedBy barOne BarProvider {\"name\" : \"barOne\"}\n * @providedBy barTwo BarProvider {\"name\" : \"barOne\"}\n */\ninterface Bar\n{\n\n}\n\nclass BarProvider implements rg\\injektor\\Provider\n{\n    private $name;\n\n    public function __construct($name)\n    {\n        $this-\u003ename = $name;\n    }\n\n    public function get()\n    {\n        switch ($this-\u003ename) {\n            case 'barOne':\n                return new BarImplOne();\n            case 'barTwo':\n                return new BarImplTwo();\n        }\n\n        return new BarImplDefault();\n    }\n}\n\nclass BarImplDefault implements Bar\n{\n\n}\n\nclass BarImplOne implements Bar\n{\n\n}\n\nclass BarImplTwo implements Bar\n{\n\n}\n```\n\nIt is also possible to name the default provider, so that our configuration looks a bit cleaner. The result is the\nsame:\n\n```php\n/**\n * @providedBy default BarProvider\n * @providedBy barOne BarProvider {\"name\" : \"barOne\"}\n * @providedBy barTwo BarProvider {\"name\" : \"barOne\"}\n */\ninterface Bar\n{\n\n}\n```\n\nCall method on object instance\n------------------------------\n\nThe container can also call methods on instances an inject all method arguments\n\n```php\nclass Foo\n{\n    /**\n     * @inject\n     */\n    public function doSomething(Bar $bar)\n    {\n    }\n}\n\nclass Bar\n{\n\n}\n\n$foo = new Foo();\n$dic-\u003ecallMethodOnObject($foo, 'doSomething');\n```\n\nOf course you can also use named injections.\n\nIt is also possible to add additional values to the method call, like with object creation:\n\n```php\n\nclass Foo\n{\n    /**\n     * @inject\n     */\n    public function doSomething(Bar $bar, $foo)\n    {\n    }\n}\n\nclass Bar\n{\n\n}\n\n$foo = new Foo();\n$dic-\u003ecallMethodOnObject($foo, 'doSomething', array('foo' =\u003e 'value'));\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fresearchgate%2Finjektor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fresearchgate%2Finjektor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fresearchgate%2Finjektor/lists"}