Dependency Injection Container Documentation

Similar documents
git-pr Release dev2+ng5b0396a

CuteFlow-V4 Documentation

aiounittest Documentation

Instagram PHP Documentation

Sensor-fusion Demo Documentation

delegator Documentation

Firebase PHP SDK. Release

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

Elegans Documentation

PHP-FCM Documentation

Feed Cache for Umbraco Version 2.0

X Generic Event Extension. Peter Hutterer

dublincore Documentation

Imagination Documentation

agate-sql Documentation

XStatic Documentation

inflection Documentation

Statsd Metrics Documentation

PyCon APAC 2014 Documentation

utidylib Documentation Release 0.4

Tailor Documentation. Release 0.1. Derek Stegelman, Garrett Pennington, and Jon Faustman

josync Documentation Release 1.0 Joel Goop and Jonas Einarsson

pydocstyle Documentation

Magento Technical Guidelines

XEP-0099: IQ Query Action Protocol

Java Relying Party API v1.0 Programmer s Guide

TWO-FACTOR AUTHENTICATION Version 1.1.0

XEP-0087: Stream Initiation

MCAFEE THREAT INTELLIGENCE EXCHANGE RESILIENT THREAT SERVICE INTEGRATION GUIDE V1.0

Open Source Used In Cisco Configuration Professional for Catalyst 1.0

Daedalus Documentation

Testworks User Guide. Release 1.0. Dylan Hackers

Asthma Eliminator MicroMedic Competition Entry

Imagination Documentation

mp3fm Documentation Release Akshit Agarwal

disspcap Documentation

Transparency & Consent Framework

mqtt-broker Documentation

Spotter Documentation Version 0.5, Released 4/12/2010

retask Documentation Release 1.0 Kushal Das

deepatari Documentation

SopaJS JavaScript library package

Industries Package. TARMS Inc.

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

Firebase Admin SDK for PHP. Release

twstock Documentation

jumpssh Documentation

Dellve CuDNN Documentation

invenio-formatter Documentation

XEP-0363: HTTP File Upload

GearmanBundle. Release

sensor-documentation Documentation

Colgate, WI

DATAGATE MK2. Box Contents. Additional Features (licenses) Features. Safety

NDIS Implementation Guide

docxtemplater Documentation

RTXAGENDA v Use Manual. A program, free and easy to use, to modify your RT4, RT5 or RT6 phonebook, on PC.

LANDISVIEW Beta v1.0-user Guide

Bldr.io Documentation

Navigator Documentation

Quality of Service (QOS) With Tintri VM-Aware Storage

Inptools Manual. Steffen Macke

RTI Connext DDS Core Libraries

ZSI: The Zolera Soap Infrastructure User s Guide. Release 2.0.0

BME280 Documentation. Release Richard Hull

Tenable Hardware Appliance Upgrade Guide

ProFont began life as a better version of Monaco 9 which is especially good for programmers. It was created circa 1987 by Andrew Welch.

Bluetooth Low Energy in C++ for nrfx Microcontrollers

RTXAGENDA v Use Manual. A program, free and easy to use, to modify your RT4 phonebook, on PC.

openresty / encrypted-session-nginx-module

webbot Documentation Release Natesh M Bhat

Getting started with Dependency Injection. Rob Allen May 2015

MEAS HTU21D PERIPHERAL MODULE

MatPlotTheme Documentation

clipbit Release 0.1 David Fraser

HCP Chargeback Collector Documentation

Django Mail Queue Documentation

Build & Launch Tools (BLT) Automating best practices for enterprise sites

XTEST Extension Library

XEP-0146: Remote Controlling Clients

ExaFMM. Fast multipole method software aiming for exascale systems. User's Manual. Rio Yokota, L. A. Barba. November Revision 1

Guest Book. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

XEP-0133: Service Administration

Compound Text Encoding

XEP-0104: HTTP Scheme for URL Data

MIT-SHM The MIT Shared Memory Extension

XEP-0042: Jabber OOB Broadcast Service (JOBS)

XEP-0399: Client Key Support

withenv Documentation

MEAS TEMPERATURE SYSTEM SENSOR (TSYS01) XPLAINED PRO BOARD

The RX Document Version 1.0 X11 Release 6.4

Paris Documentation. Release. Jamie Matthews and Simon Holywell

XEP-0361: Zero Handshake Server to Server Protocol

HTNG Web Services Product Specification. Version 2011A

VMware vcenter Log Insight Manager. Deployment Guide

User s Guide for macos with Stata and R

Git. all meaningful operations can be expressed in terms of the rebase command. -Linus Torvalds, 2015

puppet-diamond Documentation

calio / form-input-nginx-module

VTT INFORMATION TECHNOLOGY. Nipper

Transcription:

Dependency Injection Container Documentation Release v1.0.0 Filipe Silva <silvam.filipe@gmail.com> Dec 08, 2017

Contents 1 Getting started 3 1.1 Introduction............................................... 3 1.2 Basic usage................................................ 3 1.3 Installation................................................ 4 2 Definitions 5 2.1 What s a definition?........................................... 5 2.2 Value definition.............................................. 6 2.3 Factory definition............................................. 6 2.4 Alias definition.............................................. 6 2.5 Object definition............................................. 7 3 Container usage 9 3.1 Building a container........................................... 9 3.2 Constructor injection........................................... 9 3.3 Constructor auto-injection........................................ 10 3.4 Factory method.............................................. 10 4 API reference 13 4.1 Container class.............................................. 13 4.2 Container Injection interface....................................... 14 4.3 ObjectDefinition class.......................................... 15 5 Contributing 17 5.1 Pull requests............................................... 17 5.2 Running tests............................................... 17 5.3 Security.................................................. 18 6 License 19 PHP Namespace Index 21 i

ii

slick/di is an easy dependency injection container for PHP 5.6+. It aims to be very lightweight and tries to remove a lot of the guessing and magic stuff that dependency containers use those days. It also allows you to nest containers witch can become very useful if you have several packages that you reuse in your applications, allowing you to define containers with default dependencies in those packages for later override and usage them in your application. There are a lot of implementations of a dependency injection container out there and some of them are really good. Some examples are the Symfony Dependency Injection Component, Zend 2 Dependency Injection, The PHP league container, or PHP-DI just to name a few. This implementation is a result of what we thought it was the best to have in a dependency injection container. Contents 1

2 Contents

CHAPTER 1 Getting started Introduction Dependency injection is a concept that has been talked about all over the web. You probably have done it without knowing that is called dependency injection. Simply put the next line of code can describe what it is: $volvo = new Car(new Engine()); Above, Engine is a dependency of Car, and Engine was injected into Car. If you are not familiar with Dependency Injection please read this Fabien Pontencier s great series about Dependency injection. Dependency injection and dependency injection containers are tow different things. Dependency injection is a design pattern that implements inversion of control for resolving dependencies. On the other hand Dependency Injection Container is a tool that will help you create, reuse and inject dependencies. A dependency container can also be used to store object instances that you create and values that you may need to use repeatedly. A good example of this are configuration settings. Basic usage To create a dependency container we need to create at least a services.php file with all our dependency definitions: use Slick\Configuration\Configuration: use Slick\Di\Definition\ObjectDefinition; /** * Dependency injection object definition example */ return [ 'config' => function() { return Configuration::get('config'); }, 'engineservice' => ObjectDefinition::create(Engine::class) 3

]; ->with('@config') ->call('setmode')->with('simple') Now to build the dependency container we need to use the ContainerBuilder factory class like this: use Slick\Di\ContainerBuilder; $definitionsfile = DIR. '/services.php'; $container = (new ContainerBuilder($definitionsFile))->getContainer(); With that, we are ready to create and inject dependencies with our container: class Car { /** * @var EngineInterface */ protected $engine; } public function construct(engineinterface $engine) { $this->engine = $engine; } $mycar = $container->make(car::class); Installation slick/di is a php 5.6+ library that you ll have in your project development environment. Before you begin, ensure that you have PHP 5.6 or higher installed. You can install slick/di with all its dependencies through Composer. Follow instructions on the composer website if you don t have it installed yet. You can use this Composer command to install slick/di: $ composer require slick/di 4 Chapter 1. Getting started

CHAPTER 2 Definitions What s a definition? Definitions are entries in an array that instruct the container on how to create the correspondent object instance or value. Attention: Every container MUST have a definition list (associative array) in order to be created and you SHOULD always use the Slick\Di\ContainerBuilder to create your container. Lets create our dependencies.php file that will contain our dependencies definitions: /** * Dependency injection definitions file */ $services['timezone'] = 'UTC'; $services['config'] = function() { return Configuration::get('config'); }; return $services; Note: Why use PHP arrays? This question has a very simple answer. If you use other markup/style to create the container definitions file, for example.ini or.yml you will need to parse those settings and then apply them. If you use PHP arrays there is no need to parse it and the code can be directly executed, enhancing performance. 5

Value definition A value or scalar definition is used as is. The following example is a value definition: /** * Dependency injection value definition example */ $services['timezone'] = 'UTC'; return $services; Value definitions are good to store application wide constants. Factory definition With factory definition we can compute and/or control the object or value creation: /** * Dependency injection callable definition example */ $services['general.config'] = function() { return Configuration::get('config'); } return $services; It is possible to have the container instance available in the closure by defining an input argument. See the following example: /** * Dependency injection callable definition example */ $services['general.config'] = function(containerinterface $container) { $foo = $container->get('foo'); return Configuration::get('config')->get('bar', $foo); } return $services; Alias definition Alias definition is a shortcut for another defined entry: /** * Dependency injection alias definition example */ $services['config'] = '@general.config'; return $services; The alias points to an entry key and is always prefixed with an @ 6 Chapter 2. Definitions

Object definition Objects are what makes dependency containers very handy, and fun! Lets have a look at an object definition inside our dependencies.php file: namespace Services; use Services\SearchService; use Slick\Configuration\Configuration: use Slick\Di\Definition\ObjectDefinition; /** * Dependency injection object definition example */ $services['sitename'] => 'Example site'; $services['config'] => function() { return Configuration::get('config'); }; // Object definition $services['search.service'] = ObjectDefinition::create(SearchService::class) ->with('@config') ->call('setmode')->with('simple') ->call('setsitename')->with('@sitename') ->assign(20)->to('rowsperpage') ; return $services; Defining how an object is instantiated is the most important feature of a dependency container. 'search.service' is an object definition on how to instantiate a SearchService. It uses a fluent api that can easily describe the necessary steps to create a service or object. Tip: If you want to reference the container itself you can use the @container tag in the object definition file. Please check the ObjectDefinition API for a better understanding of all methods on ObjectDefinition definition. 2.5. Object definition 7

8 Chapter 2. Definitions

CHAPTER 3 Container usage Now that we have defined all of our dependencies its time to create a container that will use them. Building a container Even though Container can be instantiated as normal PHP objects do, it is advisable to use the ContainerBuilder factory to do so. It translates the definitions file(s) into DefinitionInterface objects that dependency container uses to resolve its dependencies. It also chains all the created container so that if you try to get an entry it will search over all containers in the chain. This is a very handy feature if you want, for example, to create a package that you will reuse in your applications and in that package you define a container with default dependencies and later on your application also defines a dependency container. Definitions can be overridden and the entries from your package are also available in your application container. Now lets create our container: use Slick\Di\ContainerBuilder; $container = (new ContainerBuilder( DIR. '/dependencies.php'))->getcontainer(); That s it! We now have a new created dependency container ready to create objects and inject their dependencies. Constructor injection Constructor dependency injection is considered the way we should do dependency injection and it is just passing the dependencies as arguments in the constructor. With this you do not need to created setters and your object is ready to be used right away. You can also test it in isolation by passing mocks of those dependencies. Consider the following class: class Car { 9

/** * @var EngineInterface */ private $engine; } public function construct(engineinterface $engine) { $this->engine = $engine; } This is a basic class. The car needs an engine to work, right!? Tip: In constructor dependency injection and in dependency injection in general, it is a good practice to type hint your arguments. This practice guarantees that the arguments are from that given type and PHP s core will trigger a fatal error if they are not. Now that we have a container with all its dependency definitions lets create the car using and engine that is store in the container under the diesel.engine name: $dieselcar = $container->make(car::class, '@diesel.engine'); This line of code is instructing the container that it should instantiate a Car object and it will inject the dependency that was stored under the diesel.engine name in its constructor. Take a look at Container class reference page for more information on Container::make() method. Constructor auto-injection It is also possible to have dependencies injected on objects created by Container::make() only by type hinting the parameters in the constructor: public function construct(engineinterface $engine)...... $dieselcar = $container->make(car::class);... // As construct(engineinterface $engine) is type hinted the container will look // for '@EngineInterface::class' definition and inject it. You can mix the arguments sent on Container::make() second parameter with constructor auto-injection. In this case the arguments used in this late array will override the ones container has figure out. Important: Since v2.3.0 this is the behavior of Container::make() method and an exception will be thrown whenever a parameter hint results in a missing definition, otherwise why should you create object with the dependency container? Factory method one other possibility to create classes that the container can instantiate is by implementing the ContainerInjectionInterface interface. This is a simple interface that forces the creation of the 10 Chapter 3. Container usage

object trough a factory method. Take a look at the Car class with dependency injection implementation: use Slick\Di\ContainerInjectionInterface; use slick\di\containerinterface; class Car implements ContainerInjectionInterface { /** * @var EngineInterface */ private $engine; public function construct(engineinterface $engine) { $this->engine = $engine; } /** * Creates a diesel car * * @param ContainerInterface $container * @return Car */ public static function create(containerinterface $container) { $car = new Car($container->get('diesel.engine')); return $car; } } Creating the car: $dieselcar = $container->make(car::class); The container will call the ContainerInjectionInterface::create() method passing itself as argument. Note that the responsibility for object creation is on the class itself. Form more information check the Container Injection Interface reference page. 3.4. Factory method 11

12 Chapter 3. Container usage

CHAPTER 4 API reference Container class class Slick\Di\Container Container is where your dependencies live. It holds a list of DefinitionInterface objects that can be resolved into objects or values. Slick\Di\Container::get($id) Finds an entry of the container by its identifier and returns it. $id (string) Identifier of the entry to look for. Throws NotFoundException No entry was found for this identifier. Returns An object or value that was stored or has its definition under the provided $id identifier. Slick\Di\Container::has($id) Returns true if the container can return an entry for the given identifier $id (string) Identifier of the entry to look for. Returns True if container can return an entry or false otherwise. Slick\Di\Container::register($name, $definition[, $scope, $params]) Adds a definition or a value to the container with the $name as identifier. $name (string) Identifier where the entry will be stored in. $definition (mixed) The definition or value to store. $scope (string Scope) The resolution scope. Please see Definitions page for details. Defaults to Scope::SINGLETON. 13

$params (array) An array of arguments to pass to callable (Factory) definitions. Defaults to an empty array. Returns Container itself. Useful for chaining more container calls. Tip: $definition can be any value and the container will evaluate it in order to determine what strategy it will use to resolve it latter on. The possibilities are: scalar objects: scalar values or objects are store as Value definition; @<identifier>: this is an Alias definition that will point to the definition stored under the identifier name; callable: a callable is stored as Factory definition. It will be executed when Container::get() is called for the first time and the result value will be returned in the subsequent calls. $params will be passed when executing the callable; Slick\Di\DefinitionInterface: Definition interface handle the entry resolution. In this case the container will return the resolved value of the definition. Slick\Di\Container::make($className[,...$arguments]) Creates an instance of provided class injecting its dependencies. $classname (string) The class name that the container will use to create the object. $arguments (array) An optional list of arguments to pass to the constructor. Returns An object from the type passed in the $classname argument. Tip: If you create a class that implements the Slick\Di\ContainerInjectionInterface all the $arguments that you may pass to this method will be ignored as the container will call the create() method and pass himself as an argument to that method. Please see ContainerInjectionInterface reference Container Injection interface interface Slick\Di\ContainerInjectionInterface This is an easy way of creating a class that the dependency container will know how to instantiate. It has a single method and it enforces the constructor dependency injection pattern. static create($container) Instantiates a new instance of this class. $container (Interop\Container\ContainerInterface) The service container this instance should use. Returns A new instance of this class. Tip: This is a factory method that returns a new instance of this class. The factory should pass any needed dependencies into the constructor of this class, but not the container itself. Every call to this method must return a new instance of this class; that is, it may not implement a singleton. 14 Chapter 4. API reference

ObjectDefinition class class Slick\Di\Definition\ObjectDefinition An object instantiation definition that wraps the necessary steps so that a dependency container can instantiate a given class. construct($classname) Creates a definition for provided class name. $classname (string) The class name that will be instantiated. static create($classname) Factory method to create an object definition. $classname (string) The class name that will be instantiated. Returns ObjectDefinition definition object with(...$arguments) Set the arguments for the last defined method call. constructor argument list $arguments (array) Arguments passed to object constructor Returns The object definition itself. Useful for other method calls. withconstructorargument(...$arguments) Set the arguments used to create the object. $arguments (array) Arguments passed to object constructor. Returns The object definition itself. Useful for other method calls. call($methodname) Define a method call in the freshly created object. $methodname (string) The method name to call. Returns The object definition itself. Useful for other method calls. assign($value) Set the value that will be assigned to a property. $value (mixed) The value to be assigned. Returns The object definition itself. Useful for other method calls. If no method call was defined yet it will set the to($propertyname) Assign the last defined value to the provided property. The value will be reset after its assigned. $property (string) The property name where last value will be assigned. Returns The object definition itself. Useful for other method calls. 4.3. ObjectDefinition class 15

callmethod($methodname,...$arguments) Define a method call to the method with provided name. $methodname (string) The method name to call. $arguments (array) The list of arguments to use when calling the method. Throws Slick\Exception\MethodNotFoundException if called method does not exists. Returns The object definition itself. Useful for other method calls. assignproperty($name, $value) Assigns a value to the property with provided name. $name (string) The property name. $value (mixed) The value to assign to the property. Returns The object definition itself. Useful for other method calls. resolve() Resolves the definition into an object. Returns The object as described in the definition 16 Chapter 4. API reference

CHAPTER 5 Contributing Contributions are welcome and will be fully credited. We accept contributions via Pull Requests on Github. Pull requests PSR-2 Coding Standard - The easiest way to apply the conventions is to install PHP Code Sniffer. Add tests! - Your patch won t be accepted if it doesn t have tests. Document any change in behaviour - Make sure the README.md and any other relevant documentation are kept up-to-date. Consider our release cycle - We try to follow SemVer v2.0.0. Randomly breaking public APIs is not an option. Create feature branches - Don t ask us to pull from your master branch. One pull request per feature - If you want to do more than one thing, send multiple pull requests. Send coherent history - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please squash them before submitting. Running tests We use Behat to describe features and and for acceptance tests and PHPUnit for integration and unit testing. # unit tests $ vendor/bin/phpspec run # acceptance tests $ vendor/bin/behat 17

Security If you discover any security related issues, please email silvam.filipe@gmail.com instead of using the issue tracker. 18 Chapter 5. Contributing

CHAPTER 6 License Licensed using the MIT license. Copyright (c) 2014-2017 The Slick Team <https://github.com/orgs/slickframework/people> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the Software ), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARIS- ING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19

20 Chapter 6. License

PHP Namespace Index s Slick\Di, 14 Slick\Di\Definition, 15 21

Index Symbols construct() (Slick\Di\Definition\ObjectDefinition method), 15 A assign() (Slick\Di\Definition\ObjectDefinition method), 15 assignproperty() (Slick\Di\Definition\ObjectDefinition method), 16 C call() (Slick\Di\Definition\ObjectDefinition method), 15 callmethod() (Slick\Di\Definition\ObjectDefinition method), 15 Container (class in Slick\Di), 13 ContainerInjectionInterface (interface in Slick\Di), 14 create() (Slick\Di\ContainerInjectionInterface method), 14 create() (Slick\Di\Definition\ObjectDefinition method), 15 G get() (Slick\Di\Container method), 13 H has() (Slick\Di\Container method), 13 M make() (Slick\Di\Container method), 14 O ObjectDefinition (class in Slick\Di\Definition), 15 R register() (Slick\Di\Container method), 13 resolve() (Slick\Di\Definition\ObjectDefinition method), 16 S Slick\Di (namespace), 13, 14 Slick\Di\Definition (namespace), 15 T to() (Slick\Di\Definition\ObjectDefinition method), 15 W with() (Slick\Di\Definition\ObjectDefinition method), 15 withconstructorargument() (Slick\Di\Definition\ObjectDefinition method), 15 22