💎 Flexible, compiled and full-featured Dependency Injection Container with perfectly usable autowiring and support for all new PHP 7 features.

Overview

Nette Dependency Injection (DI)

Downloads this Month Tests Coverage Status Latest Stable Version License

Introduction

Purpose of the Dependecy Injection (DI) is to free classes from the responsibility for obtaining objects that they need for its operation (these objects are called services). To pass them these services on their instantiation instead.

Nette DI is one of the most interesting part of framework. It is compiled DI container, extremely fast and easy to configure.

Documentation can be found on the website.

Support Me

Do you like Nette DI? Are you looking forward to the new features?

Buy me a coffee

Thank you!

Installation

The recommended way to install is via Composer:

composer require nette/di

It requires PHP version 8.0.

Usage

Let's have an application for sending newsletters. The code is maximally simplified and is available on the GitHub.

We have the object representing email:

class Mail
{
	public $subject;
	public $message;
}

An object which can send emails:

interface Mailer
{
	function send(Mail $mail, $to);
}

A support for logging:

interface Logger
{
	function log($message);
}

And finally, a class that provides sending newsletters:

class NewsletterManager
{
	private $mailer;
	private $logger;

	function __construct(Mailer $mailer, Logger $logger)
	{
		$this->mailer = $mailer;
		$this->logger = $logger;
	}

	function distribute(array $recipients)
	{
		$mail = new Mail;
		...
		foreach ($recipients as $recipient) {
			$this->mailer->send($mail, $recipient);
		}
		$this->logger->log(...);
	}
}

The code respects Dependency Injection, ie. each object uses only variables which we had passed into it.

Also, we have a ability to implement own Logger or Mailer, like this:

class SendMailMailer implements Mailer
{
	function send(Mail $mail, $to)
	{
		mail($to, $mail->subject, $mail->message);
	}
}

class FileLogger implements Logger
{
	private $file;

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

	function log($message)
	{
		file_put_contents($this->file, $message . "\n", FILE_APPEND);
	}
}

DI container is the supreme architect which can create individual objects (in the terminology DI called services) and assemble and configure them exactly according to our needs.

Container for our application might look like this:

class Container
{
	private $logger;
	private $mailer;

	function getLogger()
	{
		if (!$this->logger) {
			$this->logger = new FileLogger('log.txt');
		}
		return $this->logger;
	}

	function getMailer()
	{
		if (!$this->mailer) {
			$this->mailer = new SendMailMailer;
		}
		return $this->mailer;
	}

	function createNewsletterManager()
	{
		return new NewsletterManager($this->getMailer(), $this->getLogger());
	}
}

The implementation looks like this because:

  • the individual services are created only on demand (lazy loading)
  • doubly called createNewsletterManager will use the same logger and mailer instances

Let's instantiate Container, let it create manager and we can start spamming users with newsletters :-)

$container = new Container;
$manager = $container->createNewsletterManager();
$manager->distribute(...);

Significant to Dependency Injection is that no class depends on the container. Thus it can be easily replaced with another one. For example with the container generated by Nette DI.

Nette DI

Nette DI is the generator of containers. We instruct it (usually) with configuration files. This is configuration that leads to generate nearly the same class as the class Container above:

services:
	- FileLogger( log.txt )
	- SendMailMailer
	- NewsletterManager

The big advantage is the shortness of configuration.

Nette DI actually generates PHP code of container. Therefore it is extremely fast. Developer can see the code, so he knows exactly what it is doing. He can even trace it.

Usage of Nette DI is very easy. Save the (above) configuration to the file config.neon and let's create a container:

$loader = new Nette\DI\ContainerLoader(__DIR__ . '/temp');
$class = $loader->load(function($compiler) {
    $compiler->loadConfig(__DIR__ . '/config.neon');
});
$container = new $class;

and then use container to create object NewsletterManager and we can send e-mails:

$manager = $container->getByType(NewsletterManager::class);
$manager->distribute(['[email protected]', ...]);

The container will be generated only once and the code is stored in cache (in directory __DIR__ . '/temp'). Therefore the loading of configuration file is placed in the closure in $loader->load(), so it is called only once.

During development it is useful to activate auto-refresh mode which automatically regenerate the container when any class or configuration file is changed. Just in the constructor ContainerLoader append true as the second argument:

$loader = new Nette\DI\ContainerLoader(__DIR__ . '/temp', true);

Services

Services are registered in the DI container and their dependencies are automatically passed.

services:
	manager: NewsletterManager

All dependencies declared in the constructor of this service will be automatically passed. Constructor passing is the preferred way of dependency injection for services.

If we want to pass dependencies by the setter, we can add the setup section to the service definition:

services:
	manager:
		factory: NewsletterManager
		setup:
			- setAnotherService

Class of the service:

class NewsletterManager
{
	private $anotherService;

	public function setAnotherService(AnotherService $service)
	{
		$this->anotherService = $service;
	}

...

We can also add the inject: yes directive. This directive will enable automatic call of inject* methods and passing dependencies to public variables with @inject annotations:

services:
	foo:
		factory: FooClass
		inject: yes

Dependency Service1 will be passed by calling the inject* method, dependency Service2 will be assigned to the $service2 variable:

class FooClass
{
	private $service1;

	// 1) inject* method:

	public function injectService1(Service1 $service)
	{
		$this->service1 = $service1;
	}

	// 2) Assign to the variable with the @inject annotation:

	/** @inject @var Service2 */
	public $service2;
}

However, this method is not ideal, because the variable must be declared as public and there is no way how you can ensure that the passed object will be of the given type. We also lose the ability to handle the assigned dependency in our code and we violate the principles of encapsulation.

Factories

We can use factories generated from an interface. The interface must declare the returning type in the @return annotation of the method. Nette will generate a proper implementation of the interface.

The interface must have exactly one method named create. Our factory interface could be declared in the following way:

interface IBarFactory
{
	/**
	 * @return Bar
	 */
	public function create();
}

The create method will instantiate an Bar with the following definition:

class Bar
{
	private $logger;

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

The factory will be registered in the config.neon file:

services:
	- IBarFactory

Nette will check if the declared service is an interface. If yes, it will also generate the corresponding implementation of the factory. The definition can be also written in a more verbose form:

services:
	barFactory:
		implement: IBarFactory

This full definition allows us to declare additional configuration of the object using the arguments and setup sections, similarly as for all other services.

In our code, we only have to obtain the factory instance and call the create method:

class Foo
{
	private $barFactory;

	function __construct(IBarFactory $barFactory)
	{
		$this->barFactory = $barFactory;
	}

	function bar()
	{
		$bar = $this->barFactory->create();
	}
}
Comments
  • Compatibility with 7.4 preloading

    Compatibility with 7.4 preloading

    There's an issue with this package when using PHP 7.4's preloading. More specifically with this file: https://github.com/nette/di/blob/master/src/compatibility.php

    Because these class aliases are defined unconditionally, they will throw "previously declared class warnings" if the file was preloaded.

    More info: https://mobile.twitter.com/nikita_ppv/status/1208025415253659648

    opened by brendt 41
  • Added IDecoratorProvider + autowired option for decorators

    Added IDecoratorProvider + autowired option for decorators

    Adds possibility to configure decorators in extensions and also autowired option.

    Based on http://forum.nette.org/en/18888-extending-extensions-solid-modular-concept.

    opened by enumag 23
  • Alternative autowiring approach [WIP]

    Alternative autowiring approach [WIP]

    ~~All services are autowired. setAutowired(TRUE) means that service is preferred, setAutowired(FALSE) means that is autowired too, but not preferred (yes, name setAutowired(FALSE) is weird here, but this is just experiment).~~

    Only services that are excluded via $excludedClasses are not autowired.

    ~~Now you can create services FileStorage (autowired: on) and DevNullStorage (autowired: off) and access the first one via getByType('IStorage') and second one viagetByType('DevNullStorage')`.~~

    I tried a different approach

    opened by dg 21
  • ContainerBuilder: Add support for aliasing service definitions

    ContainerBuilder: Add support for aliasing service definitions

    At the moment there is no sensible way how to rename a service without massive BC break, that's why some of the "Nette" services use prefixes, some not etc. This PR tries to fix this by adding support for service aliases to ContainerBuilder. Open question is whether or not to automatically trigger deprecation warning when the old name (=alias) is used instead of the new one.

    opened by xificurk 19
  • [WIP] Added Configurator

    [WIP] Added Configurator

    When using DI on its own without some (or all) of the other nette components, one still needs something like Nette\Configurator. However Nette\Configurator is only available with nette/bootstra which requires lots of other nette/* components and that's not always desired. Therefore some basic Configurator should be added to nette/di. Then nette/bootstrap could just extend it and add what is nette-specific (default extensions, compatibility code, robot loader, tracy).

    The only thing I'm not quite sure about is how to call $this->fixCompatibility($conig) when needed (https://github.com/nette/bootstrap/blob/master/src/Bootstrap/Configurator.php#L267). I was thinking about using the onCompile event for it at first but the event handlers don't have access to the $config array. Any suggestions?

    opened by enumag 16
  • Support for PSR-11 container interop

    Support for PSR-11 container interop

    • bug report? no
    • feature request? yes

    Description

    There is PSR-11 for DI containers that aims to bring interoperability between different DI containers. PSR itself is simple and support in Nette DI would make interop with components from different frameworks easier and wouldn't bring any BC breaks.

    There are already several frameworks with PSR-11 support - ZF, Symfony, ...

    I can prepare PR if needed.

    opened by fmasa 15
  • Invalid type 'Nette\DI\?T' when accessing `Container#getByType()` from DI config

    Invalid type 'Nette\DI\?T' when accessing `Container#getByType()` from DI config

    Version: 3.0.11, bug present as of 3.0.10

    Bug Description

    If you use Container#getByType() inside of NEON configuration, it fails on resolving its return type – from Helpers#getReturnTypeAnnotation() it is returned Nette\DI\?T.

    More generally, I believe (have not tried) accessing any class with method having generic return type will fail.

    Steps To Reproduce

    In nette/web-project, create this class:

    namespace App;
    final class FakeContainer
    {
    	/**
    	 * copied from Container#getByType()
    	 * @template T
    	 * @param class-string<T> $type
    	 * @return ?T
    	 */
    	public function getService(string $type)
    	{
    		return null;
    	}
    }
    

    In services.neon, use it:

    services:
    	- App\FakeContainer::getService(HomepagePresenter::class)
    

    image

    Expected Behavior

    Run, not to fail with type check.

    opened by dakur 14
  • ContainerBuilder: removeDefinition removes from classes too

    ContainerBuilder: removeDefinition removes from classes too

    Use case:

    $containerBuilder->addDefintion('one')->setClass('stdClass');
    $containerBuilder->addDefintion('two')->setClass('stdClass');
    $containerBuilder->removeDefinition('two');
    $containerBuilder->getByType('stdClass'); // breaks, because reference to 'two' is still saved under 'stdClass'
    
    opened by TomasVotruba 14
  • Add support for @var statement[|statement...]

    Add support for @var statement[|statement...]

    Add possibility use IDE code completion based on PhpDoc

    class FooPresenter extends UI\Presenter {
      /** @var Nette\Mail\IMailer|Nette\Mail\SmtpMailer @inject */
      public $mailer;
    }
    
    opened by trejjam 13
  • Support for ENV variables

    Support for ENV variables

    Syntax could leverage support for arrays a: %env.NAME% with all variables in %env%.

    Things to consider:

    • Syntax for default values.
    • Whitelist by default.
    • Invalidate cache if used ENV has changed.
    • Interface to access them in extensions. (to complement config and add requested ENVs to whitelist)

    I have created extension to add partial support for ENV variables. It has whitelist and default values and partial support for configs. Cache invalidation is not implemented

    opened by mishak87 13
  • Wrong evaluation of injected service class when using trait

    Wrong evaluation of injected service class when using trait

    Version: 2.4.13

    Bug Description

    When property annotated with @inject exists in presenter and also in trait, and the class is denoted by relative name, the namespace of same property from trait is used.

    Steps To Reproduce

    Let's say we have a trait we intend to use in a presenter that looks like this:

    namespace App;
    
    trait TPresenter {
    	/** @var MyService @inject */
    	public $myService;
    }
    

    The service looks like this:

    namespace App;
    
    class MyService {	
    }
    

    Now we use it in presenters like this (note the namespace).

    namespace App\FrontModule;
    
    final class IndexPresenter extends \App\Presenter
    {
    	use \App\TPresenter;
    	
    	public function actionDefault()
    	{
    		bdump(get_class($this->myService)); // App\MyService
    	}
    }
    

    This works just fine. But for some reason we want to use the custom service (again, notice the namespace) that looks like this in one of our presenters.

    namespace App\FrontModule;
    
    class MyService {
    }
    

    So we alter the presenter code to look like this. Notice that although the annotation looks exactly same like the one in the trait, we actually are in a different namespace and the class should be App\FrontModule\MyService. But it still injects the App\MyService.

    namespace App\FrontModule;
    
    final class IndexPresenter extends \App\Presenter
    {
    	use \App\TPresenter;
    	
    	/** @var MyService @inject */
    	public $myService;
    	
    	public function actionDefault()
    	{
    		bdump(get_class($this->myService)); // Should be App\FrontModule\MyService, but is still App\MyService
    	}
    }
    

    Expected Behavior

    The App\FrontModule\MyService should be injected, App\MyService is injected instead.

    Another thing is that when the App\FrontModule\MyService is renamed to App\FrontModule\MyService2 I get this error: Class or interface 'App\MyService2' used in @var annotation at App\TPresenter::$myService not found. This annotation is not in the App\TPresenter so I guess this is a bug in DI evaluation of class to inject?

    Possible Solution

    Providing fully qualified class name fixes the problem but obviously is only a temporary and dangerous hack.

    opened by josefsabl 12
  • DI not accepting null value of Nette config parameter if parameter is Object

    DI not accepting null value of Nette config parameter if parameter is Object

    (the original description of the issue is outdated and there's no issue with Structure, please read the discussion below)

    Version: 3.0.13

    Bug Description

    Configuration of Nette extension can be configured by getConfigSchema() which returns Nette\Schema\Elements\Structure. The actual config is then returned as stdClass.

    Consider using this config in the extension:

    return Expect::structure([
        'redis_client_factory' => Expect::structure([
            'prefix' => Expect::string()->dynamic()->nullable(),
            'replication' => Expect::structure([
                'service' => Expect::string()->dynamic(),
                'sentinels' => Expect::arrayOf(Expect::string())->dynamic()
            ])
        ])
    ]);
    

    If I don't provide any configuration value to the redis_client_factory.prefix, the default (null) is used. All is fine to this point.

    The issue is that the DI container reports, that the redis_client_factory.prefix is missing, even if it is nullable. The reason why this happen is this snippet: https://github.com/nette/di/blob/5f0b8494f2a4ddd7185a22970e400448823fa512/src/DI/Helpers.php#L72-L78

    In the past, DI could work with the assumption that the config is always array, but it's not true anymore. Now our code throws an exception from the else branch.

    • The first condition evaluates to false, because our config ($val) is not an array, but stdClass
    • Theoretical attempt to use array_key_exists() with stdClass would work for now, but it is deprecated - you'd get "array_key_exists(): Using array_key_exists() on objects is deprecated. Use isset() or property_exists() instead".

    Steps To Reproduce

    The fastest would be to try to use such extension in your Nette application. Use the snippet from above in your testing extension.

    FooExtension
    <?php
    
    namespace Crm\FooModule\DI;
    
    use Nette;
    use Nette\DI\CompilerExtension;
    use Nette\Schema\Expect;
    
    final class FooModuleExtension extends CompilerExtension 
    {
        public function getConfigSchema(): Nette\Schema\Schema
        {
            return Expect::structure([
                'redis_client_factory' => Expect::structure([
                    'prefix' => Expect::string()->dynamic()->nullable(),
                    'replication' => Expect::structure([
                        'service' => Expect::string()->dynamic(),
                        'sentinels' => Expect::arrayOf(Expect::string())->dynamic()
                    ])
                ])
            ]);
        }
    }
    

    Now enable the extension in your Nette application:

    extensions:
    	foo: Crm\FooModule\DI\FooModuleExtension
    

    Expected Behavior

    Since the property was defined as nullable(), DI should consider "no value" defaulting to null as a valid extension configuration.

    Possible Solution

    If I understand the code correctly, another elseif branch for stdClass using property_exists() should be sufficient, but I can't tell for sure.

    Thanks for checking.

    opened by rootpd 5
  • Autoload-based automatic registration of service dependencies

    Autoload-based automatic registration of service dependencies

    If I want to have some class usable for auto-wiring, it needs to be registered in the container, otherwise auto-wiring will throw a MissingServiceException – I assume this is to prevent accidentally trying to create a random object in the container, which could hide that a class actually needs the object instantiated in a different way.

    Currently, my options are either:

    The latter is based on RobotLoader, which, in addition to repeating the work already done by Composer in most modern projects, can cause issues when some of the classes are not loadable.

    For instance, barista is a Nette-based tool and it currently uses the search extension to locate services in the src/ directory. But the src/ directory also contains some helper classes, including one that depends on PHPUnit – even though the tool itself does not depend on PHPUnit so it might not be installed. When that is indeed the case, the search extension causes it to be loaded by calling class_exists, crashing the autoloader due to a missing PHPUnit class in the process.

    Since this app is not actually needed in the first place and is only attempted to be registered due to it being in the src/ directory, I propose adding another extension for automatic registration of dependencies in addition to search that, instead of a directory, would look at the dependencies of explicitly registered services and try to register them, if they are not registered already. The interface could look something like the following:

    autoloaderRegistration:
        # Registers any dependency required by services that is in the Barista namespace:
        namespace: 'Barista\\'
        excludes:
          - 'Barista\\Testing\\'
    

    Would that be possible to implement? My main worry would be that the container also supports runtime auto-wiring of classes that are not registered. Dependency trees of those would not be available to the compiler. But that does not seem to be the case if I am looking at DI\Autowiring correctly. And even if it were, we could just have ignored those.

    opened by jtojnar 2
  • Service inject initiator

    Service inject initiator

    Very often I need to find out which service caused another service to load.

    For example, I call a request where a lot of services are injected that won't be needed in the end. In a complex application, it is hard to discover the exact reason why a service was instantiated.

    I suggest adding a switch to the configuration to enable path tracing of how services were instantiated, for better debug. The information could be displayed directly in the Tracy panel.

    Now the path can be found out by throwing an exception, for example:

    Snímek obrazovky 2022-02-03 v 11 42 55

    Thanks.

    opened by janbarasek 0
  • SchemaExtension

    SchemaExtension

    • new feature 🎉
    • BC break? no
    • doc PR: Okay, but later please.

    Any key in neon can be validated with neon-defined nette/schema, via SchemaExtension:

    extensions:
    	schema: Nette\DI\Extensions\SchemaExtension
    
    schema:
    	string: string()
    	structure: structure([
    		string: string(),
    		stringWithDefault: schema(string("default value"), required(false))
    		int: int(),
    		float: float(),
    		bool: bool(),
    		array: arrayOf(string())
    		list: listOf(string())
    		type: type("string|int")
    		schema1: schema(string())
    		schema2: schema(string(), nullable())
    		schema3: schema(string(), nullable(), required(false))
    		schema4: schema(int(), min(10), max(20))
    

    Behavior differs from direct use of nette/schema

    • all keys defined in schema are required by default (should make the most common usecase of neon-defined schema simpler)
    • additional configuration which is done via chained method can be achieved via schema(), eg. Expect::int()->min(10)->max(20) -> schema(int(), min(10), max(20))

    Requirements of schema above could be satisfied with this example configuration:

    string: string
    structure:
    	string: text
    	int: 123
    	float: 123.456
    	bool: true
    	array: [key: string, anotherString]
    	list: [string, anotherString]
    	type: string
    	schema1: string
    	schema2: null
    	#schema3 is not required
    	schema4: 15
    

    Keys not defined in schema are allowed and accept any value just like before this PR. So e.g. this is allowed:

    services:
    	- Example
    

    TODOs

    • docs
    • bootstrap integration

    Big thanks to author of original extension which validates parameters in PHPStan, @ondrejmirtes

    opened by mabar 2
Releases(v3.1.0)
  • v3.1.0(Dec 5, 2022)

    Changes:

    • supports PascalCase constants in configuration
    • Resolver: non-optional autowired parameters trigger notice that value is required [Closes #271]
    • constants are PascalCase
    • NeonAdapter: automatically escapes @
    • Compiler: constants are evaluated immediately"

    Deprecations:

    • deprecated options 'parameters', 'dynamic', 'class' (instead of 'type') in configuration
    • Three ... dots are deprecated in configuration
    • Loader::save() is deprecated
    • annotations @return are deprecated
    • PhpExtension & ConstantsExtension are deprecated (have been moved to nette/bootstrap)
    Source code(tar.gz)
    Source code(zip)
  • v3.0.14(Nov 2, 2022)

  • v3.0.13(Mar 10, 2022)

    • private constants are PascalCase
    • Resolver: autowiring of collection supports 'array`<int,T>`` annotation #277
    • composer: updated dependencies
    • DefinitionSchema: recognizes Locator with one service #276
    Source code(tar.gz)
    Source code(zip)
  • v3.0.12(Dec 14, 2021)

    • Resolver::resolveEntityType() ignores return types 'object' & 'mixed' #274
    • Resolver::autowireArgument() uses named arguments to skip optional parameters in PHP 8
    • Resolver: forbidden to use extra parameter after optional (for forward compatibility) (BC break)
    • Resolver::autowireArguments() improved support for variadics
    • Resolver: refactoring of autowireArguments()
    • ServicesExtension: improved parameter merging method
    • DependencyChecker: do not serialize object parameters #273
    • PhpGenerator: do not format the statement twice or incorrectly
    • improved exception messages
    • improved coding style
    • ServiceDefinition: added setCreator() & getCreator(), aliases for setFactory() & getFactory()
    Source code(tar.gz)
    Source code(zip)
  • v3.0.11(Oct 26, 2021)

    • The _ are removed using Neon visitor #264 (requires neon/neon 3.3)
    • InjectExtension: warns on non-public, static or readonly properties
    • ServiceDefinition: type checking removed, because methods have a type defined
    • FactoryDefinition: fixed notice #266
    • Partially reverts "improved phpDoc, used generics (#261)" #263
    • Revert "Resolver::autowireArguments() throws an exception when combining a named and positional parameter" #265
    Source code(tar.gz)
    Source code(zip)
  • v3.0.10(Sep 29, 2021)

    • added _ as alias for ... in config
    • FactoryDefinition: added support for syntax $params in definition
    • added 'create' as alias for 'factory'
    • Resolver::autowireArguments() throws an exception when combining a named and positional parameter
    • DefinitionSchema: better exception on empty definition
    • FactoryDefinition::resolveType() checks for type compatibility
    • Resolver::completeException() truncates but does not remove the class name
    • Unified type validation using Helper::ensureClassType()
    • replaced use of Reflection::getReturnTypes() etc
    • uses nette/utils 3.1.6
    • improved phpDoc, used generics (#261)
    Source code(tar.gz)
    Source code(zip)
  • v3.0.9(Aug 25, 2021)

    • support for PHP 8.1
    • improved error messages
    • added support for enums in config file
    • support for intersection type
    • Revert "uses nette/utils 3.2" to maintain compatibility with PHP 7.1
    Source code(tar.gz)
    Source code(zip)
  • v3.0.8(Mar 2, 2021)

    • Resolver: handles nullable or default union|types
    • ContainerPanel: better sorting for human eyes
    • ContainerPanel: shows names of anonymous services
    • uses nette/utils 3.2
    Source code(tar.gz)
    Source code(zip)
  • v3.0.7(Dec 31, 2020)

  • v3.0.6(Nov 25, 2020)

    • added PHP 8 attribute Inject
    • cooperation with union types
    • Resolver::completeException() appends entity to exception message when type is not known
    • DependencyChecker: checks types of properties
    • DependencyChecker: fixed compatibility with PHP 8 #247
    • DIExtension: detects Tracy by presence of service @Tracy\Bar #245
    • InjectExtension: updated exception messages

    For the details you can have a look at the diff.

    Source code(tar.gz)
    Source code(zip)
  • v2.4.17(Nov 25, 2020)

  • v3.0.5(Aug 13, 2020)

    • compatible with PHP 8.0
    • added new internal functions bool(), int(), float(), string()
    • added Helpers::escape()
    • improved exception messages

    For the details you can have a look at the diff.

    Source code(tar.gz)
    Source code(zip)
  • v3.0.4(May 15, 2020)

    • Resolver: fixed self-dependency #240
    • InjectExtension: chooses a more specific type #234
    • SearchExtension: Exception when class is not autoloaded.
    • DecoratorExtension: resolves definitions before uses its findByType()
    • Container: added getByName() as alias for getService()
    • Compiler: moved Search extension before Decorator (#197)
    • Resolver: better exception message (#233)
    • InjectExtension: maintains natural order of inject methods (BC break)

    For the details you can have a look at the diff.

    Source code(tar.gz)
    Source code(zip)
  • v3.0.3(Jan 20, 2020)

    • CompilerExtension: added $initialization as replacement for modifying initialize() method
    • class aliases are loaded on demand #226
    • Statement: can be used as dynamic parameter #228
    • parameters: dynamic parameters are resolved
    • parameters: statements are replaced with null in Container
    • %parameters% resolves to all parameters
    • Revert "parameters can contain statements #221"
    • ContainerPanel: uses capturing

    For the details you can have a look at the diff.

    Source code(tar.gz)
    Source code(zip)
  • v3.0.2(Dec 27, 2019)

    • InjectExtension: accepts native type
    • parameters can contain statements #221
    • InjectExtension: scans resolved class #218
    • SearchExtension: removes conflicting services before it starts to add them
    • Resolver.autowireArguments() fixed counting optional args
    • Resolver::autowireArguments() refactoring, added autowireArgument(), Resolver|Container replaced with callback
    • ExtensionsExtension: better exception message #219

    For the details you can have a look at the diff.

    Source code(tar.gz)
    Source code(zip)
  • v2.4.16(Nov 19, 2019)

  • v3.0.1(Aug 7, 2019)

    • SearchExtension: ability to add factory definitions from interfaces with method create() (#200)
    • Revert "Container: deprecated support for dynamically added services (BC break)" #203
    • ServiceDefinition: removed unnecessary $service variable #206
    • Autowiring: bug fix & tests
    • ExtensionsExtension: added extension type checking (#209)
    • fixed bugs reported by PhpStan (#212)(#211)(#210)(#208)(#207)(#213)(#214)
    • PHP 7.4 compatibility fixes

    For the details you can have a look at the diff.

    Source code(tar.gz)
    Source code(zip)
  • v3.0.0(Apr 3, 2019)

    Features

    • requires PHP 7.1
    • uses declare(strict_types=1)
    • uses PHP 7.1 scalar and return type hints
    • autowiring via Service[] (#178)
    • added collections via tagged() and typed()
    • added SearchExtension
    • added Schema & CompilerExtension::getConfigSchema() for automatic configuration validation with PHP 7.4 support #191
    • added full validation of dynamic parameters
    • configs are normalized before merge
    • added AccessorDefinition, FactoryDefinition, LocatorDefinition & ImportedDefinition
    • Container::addService() accepts factory closures
    • Minification of metadata: added option 'di › export › types', tags and parameters
    • added Reference, object representing reference to @service of @\Class
    • better exception messages
    • Helpers::expand() expands %params% in keys [Closes nette/nette#766]
    • Helpers::expand() supports %dynamic.item% for dynamic parameters
    • Compiler, CompilerExtension: improved Loader extendability (#62)
    • ServiceDefinition::setArgument() added [Closes #171][Closes #172]
    • Processor: names of anonymous services are just numbers
    • ContainerBuilder::addDefinition(null) adds anonymous service
    • added PhpStorm metadata for autocompletion
    • added CompilerExtension::loadDefinitionsFromConfig()
    • Loader: added support for %param% in 'include' section [Closes #170][Closes phpstan/phpstan#2020]

    Changes

    • removed deprecated support for inheritance 'child < parent' (BC break)
    • some classes & members marked as final (BC break)
    • Compiler: container has declare(strict_types=1)
    • removed unused PhpReflection
    • Processor::filterArguments() translates @service to object Reference
    • Nette\DI\Helpers::filterArguments() moved to Nette\DI\Config\Processor
    • Config\Processor: options 'class' & 'type', 'dynamic' & 'imported' are aliases
    • Compiler::loadDefinitions() is not static and removed first parameter (BC break)
    • Compiler::loadDefinition() is deprecated (BC break)
    • Compiler: processing of config files moved to new class Nette\DI\Config\Processor
    • ServiceDefinition divided into Definition & ServiceDefinition
    • ContainerBuilder divided into Autowiring & Resolver
    • ServiceDefinition & Statement moved to Nette\DI\Definitions namespace
    • renamed Nette\DI\Config\IAdapter -> Adapter
    • NeonAdapter: added deprecation notice for operator ?
    • removed IniAdapter (BC break) (#177)
    • ServiceBuilder::setType() & getType() as a replacements for setClass() and getClass()
    • Compiler: added configuration option 'type' as replacement for 'class'
    • ServiceDefinition::setClass() parameter $args is deprecated (BC break) (#146)
    • Compiler::loadDefinitions() renamed to loadDefinitionsFromConfig(), better deprecation messages
    • InjectExtension: tag 'inject' changed to 'nette.inject'
    • DIExtension: tag 'run' is deprecated (BC break)
    • Container: deprecated support for dynamically added services (BC break)
    • Container: removed support for statically added createService* methods (BC break)
    • Container::$meta divided to $types, $aliases, $tags & $wiring (BC break)
    • Helpers::EXTENDS_KEY & OVERWRITE replaced with PREVENT_MERGING (BC break)
    Source code(tar.gz)
    Source code(zip)
  • v2.4.15(Jan 30, 2019)

    • compatibility with nette/php-generator 3.x #182
    • updated to nette/utils 2.5
    • ContainerBuilder: improved error messages
    • Container: removed leading __ from anonymous method names
    • Compiler: names of anonymous services are just numbers
    • Compiler::loadDefinitions() sorts definitions only if needed
    • Compiler: added option 'imported' as alias for 'dynamic'
    • CompilerExtension::validateConfig() prints 'section › value' instead of section.value in exception message
    • added PhpStorm metadata for autocompletion
    • PhpGenerator: fixed type of generated factories in Container $meta

    For the details you can have a look at the diff.

    Source code(tar.gz)
    Source code(zip)
  • v2.4.14(Sep 18, 2018)

    • ContainerBuilder::resolveImplement supports polymorphism (#175)
    • Helpers::expand() supports %dynamic.item% for dynamic parameters

    For the details you can have a look at the diff.

    Source code(tar.gz)
    Source code(zip)
  • v2.4.13(Jun 28, 2018)

    • ContainerBuilder::completeStatement() improved error message
    • Helpers::autowireArguments() improved error message
    • ServiceCreationException: can alter exception message
    • names in error "Multiple services of type ..." are sorted
    • ContainerBuilder: fixed type of service

    For the details you can have a look at the diff.

    Source code(tar.gz)
    Source code(zip)
  • v2.4.12(May 17, 2018)

  • v2.4.11(Apr 2, 2018)

    • DecoratorExtension: do not decorate accessors by inner type (possible BC break)
    • ContainerBuilder: added check that accessor have no setup
    • Loader: add includes recursive limitation #164 #162
    • ContainerBuilder: added service type to ServiceCreationException (#151)

    For the details you can have a look at the diff.

    Source code(tar.gz)
    Source code(zip)
  • v2.4.10(Sep 6, 2017)

    • supports PHP up to 7.2
    • added ServiceBuilder::setType() & getType() as a future replacements for setClass() and getClass()
    • Compiler: added configuration option 'type' as a future replacement for 'class'
    • Loader: fixed including of paths with scheme in config loader (#153)
    • ContainerLoader: better error message when is unable to create file
    • ContainerLoader: throws exception when is unable to create directory

    For the details you can have a look at the diff.

    Source code(tar.gz)
    Source code(zip)
  • v2.4.9(Jul 14, 2017)

    • coding style: fixes, lowercase true/false/null
    • added support for class aliases created via class_alias() #156
    • DependencyChecker: class is expired when parent/interfaces/traits was changed
    • DecoratorExtension: accepts setup syntax '$prop = val'
    • ContainerBuilder: allows ::Namespace\func as factory name
    • generated factories: fix return type, PHP does not support return type covariance (#152)
    • removed unnecessary ltrim($class, '\')

    For the details you can have a look at the diff.

    Source code(tar.gz)
    Source code(zip)
  • v2.4.8(Mar 17, 2017)

    • Compiler::loadDefinitions: allow to get to existing service by class #145
    • ContainerBuilder::getByType() added argument $throw
    • DependencyChecker::isExpired() can alter $phpFiles modification times #144
    • Helpers::getReturnType() ignores 'object' and 'mixed'
    • PhpGenerator: removed unnecessary type checking in PHP 7
    • uses nette/php-generator 2.6.1 wildcards
    • ContainerBuilder: create_function() replaced with eval()

    For the details you can have a look at the diff.

    Source code(tar.gz)
    Source code(zip)
  • v2.3.14(Mar 17, 2017)

    • compatibility with nette/php-generator v2.6 #150
    • ContainerBuilder: create_function() replaced with eval()
    • tests: fixed mkdir() race condition
    • each() replaced with current() and next()

    For the details you can have a look at the diff.

    Source code(tar.gz)
    Source code(zip)
  • v2.4.7(Feb 19, 2017)

    • added dynamic parameters #61
    • Compiler::addExtension() allows empty name
    • each() replaced with current() and next()
    • ContainerBuilder: ltrims \ from service class
    • Helpers::expand supports concatenation of PhpLiteral
    • ContainerBuilder: disable autowiring for aliases only when autowired is TRUE

    For the details you can have a look at the diff.

    Source code(tar.gz)
    Source code(zip)
  • v2.4.6(Jan 15, 2017)

    • PhpGenerator: generates native return type hints
    • Compiler: added option 'alteration'
    • ContainerBuilder: getDefinitionByType() method added #130 (#137)
    • ContainerBuilder::literal() can have arguments
    • Compiler: fixed notice when overwriting service
    • uses Nette\Utils\Reflection::getParameterDefaultValue() to prevent Fatal Error when invalid constant is used
    • nette/php-generator updated to 2.5.0
    • compatibility with nette/php-generator v3

    For the details you can have a look at the diff.

    Source code(tar.gz)
    Source code(zip)
  • v2.4.5(Dec 23, 2016)

    • ContainerBuilder: support for nullable types in generated factories #132
    • DependencyChecker: fixed serialization of returnType, supports nullable types
    • Config\Loader: allow absolute paths in includes section (#131)
    • IniAdapter, NeonAdapter: process() is public #134
    • @return self -> static

    For the details you can have a look at the diff.

    Source code(tar.gz)
    Source code(zip)
Twittee is the smallest, and still useful, Dependency Injection Container in PHP

What is Twittee? Twittee is the smallest, and still useful, Dependency Injection Container in PHP; it is also probably one of the first public softwar

null 133 Dec 5, 2022
A small PHP dependency injection container

Pimple Caution! Pimple is now closed for changes. No new features will be added and no cosmetic changes will be accepted either. The only accepted cha

Silex 2.6k Dec 29, 2022
PSR-11 compatible Dependency Injection Container for PHP.

bitexpert/disco This package provides a PSR-11 compatible, annotation-based dependency injection container. Have a look at the disco-demos project to

bitExpert AG 137 Sep 29, 2022
The dependency injection container for humans

layout home PHP-DI is a dependency injection container meant to be practical, powerful, and framework-agnostic. Read more on the website: php-di.org G

null 2.4k Jan 4, 2023
Small but powerful dependency injection container

Container (Dependency Injection) This package is compliant with PSR-1, PSR-2, PSR-4 and PSR-11. If you notice compliance oversights, please send a pat

The League of Extraordinary Packages 779 Dec 30, 2022
Dependency Injection System

Aura.Di A serializable dependency injection container with constructor and setter injection, interface and trait awareness, configuration inheritance,

Aura for PHP 342 Dec 1, 2022
Yii Dependency Injection PSR-11 compatible

Yii Dependency Injection PSR-11 compatible dependency injection container that is able to instantiate and configure classes resolving dependencies. Fe

Yii Software 161 Nov 10, 2022
This repository holds all interfaces related to PSR-11 (Container Interface).

Container interface This repository holds all interfaces related to PSR-11 (Container Interface). Note that this is not a Container implementation of

PHP-FIG 9.6k Jan 4, 2023
Dependency Manager for PHP

Composer - Dependency Management for PHP Composer helps you declare, manage, and install dependencies of PHP projects. See https://getcomposer.org/ fo

Composer 27.2k Dec 31, 2022
IoC Dependency Injector

auryn auryn is a recursive dependency injector. Use auryn to bootstrap and wire together S.O.L.I.D., object-oriented PHP applications. How It Works Am

Daniel Lowrey 725 Nov 23, 2022
IoC Dependency Injector

auryn auryn is a recursive dependency injector. Use auryn to bootstrap and wire together S.O.L.I.D., object-oriented PHP applications. How It Works Am

Daniel Lowrey 710 Apr 15, 2021
DI Container (PSR-11)

My DI Container It's my own implementation PSR-11 Container Interface. Installation composer require scruwi/container Init $container = new Container(

null 4 Mar 15, 2022
Extensible DI container for Symfony2

This package contains an implementation of the Symfony 2 DI container that can be extended using other DI containers (from other frameworks).

TheCodingMachine 1 Apr 2, 2014
Adapters for PHP framework containers to an interoperable interface

Acclimate - Container Adapters Get Acclimated! Use any third-party dependency injection containers and service locators in your code by adapting them

Acclimate Container 215 Dec 16, 2022
The DependencyInjection component allows you to standardize and centralize the way objects are constructed in your application.

DependencyInjection Component The DependencyInjection component allows you to standardize and centralize the way objects are constructed in your appli

Symfony 3.9k Dec 28, 2022
🚀 PHP Service Container with fast and cachable dependency injection.

ClanCats Container A PHP Service Container featuring a simple meta-language with fast and compilable dependency injection. Requires PHP >= 7.0 Pros: M

ClanCats 28 Apr 13, 2022
Twittee is the smallest, and still useful, Dependency Injection Container in PHP

What is Twittee? Twittee is the smallest, and still useful, Dependency Injection Container in PHP; it is also probably one of the first public softwar

null 133 Dec 5, 2022
A small PHP dependency injection container

Pimple Caution! Pimple is now closed for changes. No new features will be added and no cosmetic changes will be accepted either. The only accepted cha

Silex 2.6k Dec 29, 2022
PSR-11 compatible Dependency Injection Container for PHP.

bitexpert/disco This package provides a PSR-11 compatible, annotation-based dependency injection container. Have a look at the disco-demos project to

bitExpert AG 137 Sep 29, 2022
The dependency injection container for humans

layout home PHP-DI is a dependency injection container meant to be practical, powerful, and framework-agnostic. Read more on the website: php-di.org G

null 2.4k Jan 4, 2023