2017 © Pedro Peláez
 

library injector

Config-driven extension of Auryn Dependency Injector.

image

brightnucleus/injector

Config-driven extension of Auryn Dependency Injector.

  • Wednesday, January 17, 2018
  • by schlessera
  • Repository
  • 1 Watchers
  • 4 Stars
  • 967 Installations
  • PHP
  • 1 Dependents
  • 0 Suggesters
  • 1 Forks
  • 2 Open issues
  • 15 Versions
  • 11 % Grown

The README.md

Bright Nucleus Injector Component

Config-driven Dependency Injector, based in large parts on Auryn., (*1)

Build Status Latest Stable Version Total Downloads License, (*2)

This is a config-driven dependency injector, to allow easy registration of alias mappings through the brightnucleus/config component., (*3)

It includes large parts of code from the rdlowrey/auryn package., (*4)

Notable changes compared to Auryn:, (*5)

  • Injector configuration can be done through a Config file.
  • Aliases are case-sensitive.
  • Closures can receive an InjectionChain object that let you iterate over the instantiation hierarchy.

Table Of Contents

Requirements

BrightNucleus Injector requires PHP 7.0+., (*6)

Installation

The best way to use this component is through Composer:, (*7)

composer require brightnucleus/injector

Basic Usage

This documentation only deals with passing in mappings through a Config file. Documentation for the basic methods still needs to be synced. For now, just refer to the Auryn README for these.., (*8)

The Bright Nucleus Injector expects to get an object through its constructor that implements the BrightNucleus\Config\ConfigInterface. You need to pass in the correct "sub-configuration", so that the keys that the Injector is looking for are found at the root level., (*9)

The Injector looks for three configuration keys: standardAliases, sharedAliases and configFiles., (*10)

The injector works by letting you map aliases to implementations. An alias is a specific name that you want to be able to instantiate. Aliases can be classes, abstract classes, interfaces or arbitrary strings. You can map each alias to a concrete implementation that the injector should instantiate., (*11)

This allows you to have your classes only depend on interfaces, through constructor injection, and choose the specific implementation to use through the injector config file., (*12)

As an example, imagine the following class:, (*13)

class BookReader
{
    /** @var BookInterface */
    protected $book;

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

    public function read()
    {
        echo $this->book->getContents();
    }
}

If we now define an alias 'BookInterface' => 'LatestBestseller', we can have code like the following:, (*14)

<?php
$bookReader = $injector->make('BookReader');
// This will now echo the result of LatestBestseller::getContents().
$bookReader->read();

Standard Aliases

A standard alias is an alias that behaves like a normal class. So, for each new instantiation (using Injector::make()), you'll get a fresh new instance., (*15)

Standard aliases are defined through the Injector::STANDARD_ALIASES configuration key:, (*16)

// Format:
//    '<class/interface>' => '<concrete class to instantiate>',
Injector::STANDARD_ALIASES => [
    'BrightNucleus\Config\ConfigInterface' => 'BrightNucleus\Config\Config',
]

Shared Aliases

A shared alias is an alias that behaves similarly to a static variable, in that they get reused across all instantiations. So, for each new instantiation (using Injector::make()), you'll get exactly the same instance each time. The object is only truly instantiated the first time it is needed, and this instance is then shared., (*17)

Shared aliases are defined through the Injector::SHARED_ALIASES configuration key:, (*18)

// Format:
//    '<class/interface>' => '<concrete class to instantiate>',
Injector::SHARED_ALIASES => [
    'ShortcodeManager' => 'BrightNucleus\Shortcode\ShortcodeManager',
]

Argument Definitions

The argument definitions allow you to let the Injector know what to pass in to arguments when you need to inject scalar values., (*19)

// Format:
//
// '<alias to provide argument for>' => [
//    '<argument>' => '<callable or scalar that returns the value>',
// ],
Injector::ARGUMENT_DEFINITIONS => [
    'PDO' => [
        'dsn'      => $dsn,
        'username' => $username,
        'passwd'   => $password,
    ]
]

By default, the values you pass in as definitions are assumed to be raw values to be used as they are. If you want to pass in an alias through the Injector::ARGUMENT_DEFINITIONS key, wrap it in a BrightNucleus\Injector\Injcetion class, like so:, (*20)

Injector::ARGUMENT_DEFINITIONS => [
    'config' => [
        'config' => new Injection( 'My\Custom\ConfigClass' ),
    ]
]

Argument Providers

The argument providers allow you to let the Injector know what to pass in to arguments when you need to instantiate objects, like $config or $logger. As these are probably different for each object, we need a way to map them to specific aliases (instead of having one global value to pass in). This is done by mapping each alias to a callable that returns an object of the correct type., (*21)

The Injector will create a light-weight proxy object for each of these. These proxies are instantiated and replaced by the real objects when they are first referenced., (*22)

As an example, pretty much all of the Bright Nucleus components use Config files to do project-specific work., (*23)

If you want to map aliases to specific subtrees of Config files, you can do this by providing a callable for each alias. When the Injector tries to instantiate that specific alias, it will invoke the corresponding callable and hopefully get a matching Config back., (*24)

// Format:
// '<argument>' => [
//    'interface' => '<interface/class that the argument accepts>',
//    'mappings'  => [
//        '<alias to provide argument for>' => <callable that returns a matching object>,
//    ],
// ],
Injector::ARGUMENT_PROVIDERS => [
    'config' => [
        'interface' => ConfigInterface::class,
        'mappings'  => [
            ShortcodeManager::class => function ($alias, $interface) {
                return ConfigFactory::createSubConfig(
                    __DIR__ . '/config/defaults.php',
                    $alias
                );
            },
        ],
    ],
]

Delegations

The delegations allow you to let the Injector delegate the instantiation for a given alias to a provided factory. The factory can be any callable that will return an object that is of a matching type to satisfy the alias., (*25)

If you need to act on the injection chain, like finding out what the object is for which you currently need to instantiate a dependency, add a BrightNucleus\Injector\InjectionChain $injectionChain argument to your factory callable. You will then be able to query the passed-in injection chain. To query the injection chain, pass the index you want to fetch into InjectionChain::getByIndex($index). If you provide a negative index, you will get the nth element starting from the end of the queue counting backwards., (*26)

As an example, consider an ExampleClass with a constructor __construct( ExampleDependency $dependency ). The injection chain would be the following (in namespace Example\Namespace) :, (*27)

[0] => 'Example\Namespace\ExampleClass'
[1] => 'Example\Namespace\ExampleDependency'

So, in the example below, we use getByIndex(-2) to fetch the second-to-last element from the list of injections., (*28)

// Format:
//    '<alias>' => <callable to use as factory>
Injector::DELEGATIONS => [
    'Example\Namespace\ExampleDependency' => function ( InjectionChain $injectionChain ) {
        $parent = $injectionChain->getByIndex(-2);
        $factory = new \Example\Namespace\ExampleFactory();
        return $factory->createFor( $parent );
    },
]

Preparations

The preparations allow you to let the Injector define additional preparation steps that need to be done after instantiation, but before the object if actually used., (*29)

The callable will receive two arguments, the object to prepare, as well as a reference to the injector., (*30)

// Format:
//    '<alias>' => <callable to execute after instantiation>
Injector::PREPARATIONS => [
    'PDO' => function ( $instance, $injector ) {
        /** @var $instance PDO */
        $instance->setAttribute(
            PDO::ATTR_DEFAULT_FETCH_MODE,
            PDO::FETCH_OBJ
        );
    },
]

Registering Additional Mappings

You can register additional mappings at any time by simply passing additional Configs to the Injector::registerMappings() method. It takes the exact same format as the constructor., (*31)

$config = ConfigFactory::create([
    Injector::STANDARD_ALIASES => [
        'ExampleInterface' => 'ConcreteExample'
    ]
]);
$injector->registerMappings($config);
// Here, `$object` will be an instance of `ConcreteExample`.
$object = $injector->make('ExampleInterface');

Note: For such a simple example, creating a configuration file is of course overkill. You can just as well use the basic Auryn alias functionality and just Injector::alias() an additional alias. Refer to the Auryn Documentation to read more about the different ways of configuring the injector manually., (*32)

Contributing

All feedback / bug reports / pull requests are welcome., (*33)

This package uses the PHP Composter PHPCS PSR-2 package to check committed files for compliance with the PSR-2 Coding Style Guide. If you have valid reasons to skip this check, add the --no-verify option to your commit command:, (*34)

git commit --no-verify

License

This code is released under the MIT license., (*35)

For the full copyright and license information, please view the LICENSE file distributed with this source code., (*36)

Large parts of this code were initially taken from the rdlowrey/auryn project., (*37)

Copyright for the original Auryn code is (c) 2013-2014 Daniel Lowrey, Levi Morrison, Dan Ackroyd., (*38)

Auryn contributor list, (*39)

The Versions

17/01 2018

dev-master

9999999-dev

Config-driven extension of Auryn Dependency Injector.

  Sources   Download

MIT

The Requires

 

The Development Requires

17/01 2018
27/03 2017
11/02 2017
10/02 2017
07/01 2017
25/07 2016
28/04 2016
28/04 2016
28/04 2016