PluginProbe ʕ •ᴥ•ʔ
Cookiebot by Usercentrics – Automatic Cookie Banner for GDPR/CCPA & Google Consent Mode / 3.6.2
Cookiebot by Usercentrics – Automatic Cookie Banner for GDPR/CCPA & Google Consent Mode v3.6.2
4.7.2 4.7.1 trunk 2.3.0 2.4.0 2.4.1 2.4.2 2.5.0 3.0.0 3.0.1 3.1.0 3.10.0 3.10.1 3.11.1 3.11.2 3.11.3 3.2.0 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.6.1 3.6.2 3.6.5 3.6.6 3.7.0 3.7.1 3.8.0 3.9.0 4.0.0 4.0.1 4.0.2 4.0.3 4.1.0 4.1.1 4.2.0 4.2.1 4.2.10 4.2.11 4.2.12 4.2.13 4.2.14 4.2.2 4.2.3 4.2.4 4.2.5 4.2.6 4.2.7 4.2.8 4.2.9 4.3.0 4.3.1 4.3.10 4.3.11 4.3.12 4.3.2 4.3.3 4.3.4 4.3.5 4.3.6 4.3.7 4.3.7.1 4.3.8 4.3.9 4.3.9.1 4.4.0 4.4.1 4.4.2 4.5.0 4.5.1 4.5.10 4.5.11 4.5.2 4.5.3 4.5.4 4.5.5 4.5.6 4.5.7 4.5.8 4.5.9 4.6.0 4.6.1 4.6.2 4.6.3 4.6.4 4.6.5 4.6.6 4.6.7 4.7.0
cookiebot / addons / lib / ioc / php-di / invoker / README.md
cookiebot / addons / lib / ioc / php-di / invoker Last commit date
doc 7 years ago src 7 years ago CONTRIBUTING.md 7 years ago LICENSE 7 years ago README.md 7 years ago composer.json 7 years ago
README.md
235 lines
1 # Invoker
2
3 Generic and extensible callable invoker.
4
5 [](https://travis-ci.org/PHP-DI/Invoker![Build Status](https://img.shields.io/travis/PHP-DI/Invoker.svg?style=flat-square)](https://travis-ci.org/PHP-DI/Invoker](https://travis-ci.org/PHP-DI/Invoker)
6 [](https://coveralls.io/r/PHP-DI/Invoker?branch=master![Coverage Status](https://img.shields.io/coveralls/PHP-DI/Invoker/master.svg?style=flat-square)](https://coveralls.io/r/PHP-DI/Invoker?branch=master](https://coveralls.io/r/PHP-DI/Invoker?branch=master)
7 [](https://scrutinizer-ci.com/g/PHP-DI/Invoker/?branch=master![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/PHP-DI/Invoker.svg?style=flat-square)](https://scrutinizer-ci.com/g/PHP-DI/Invoker/?branch=master](https://scrutinizer-ci.com/g/PHP-DI/Invoker/?branch=master)
8 [](https://packagist.org/packages/PHP-DI/invoker![Latest Version](https://img.shields.io/github/release/PHP-DI/invoker.svg?style=flat-square)](https://packagist.org/packages/PHP-DI/invoker](https://packagist.org/packages/PHP-DI/invoker)
9
10 ## Why?
11
12 Who doesn't need an over-engineered `call_user_func()`?
13
14 ### Named parameters
15
16 Does this [](http://silex.sensiolabs.orgSilex](http://silex.sensiolabs.org](http://silex.sensiolabs.org) example look familiar:
17
18 ```php
19 $app->get('/project/{project}/issue/{issue}', function ($project, $issue) {
20 // ...
21 });
22 ```
23
24 Or this command defined with [](https://github.com/mnapoli/silly#usageSilly](https://github.com/mnapoli/silly#usage](https://github.com/mnapoli/silly#usage):
25
26 ```php
27 $app->command('greet [name] [--yell]', function ($name, $yell) {
28 // ...
29 });
30 ```
31
32 Same pattern in [](http://www.slimframework.comSlim](http://www.slimframework.com](http://www.slimframework.com):
33
34 ```php
35 $app->get('/hello/:name', function ($name) {
36 // ...
37 });
38 ```
39
40 You get the point. These frameworks invoke the controller/command/handler using something akin to named parameters: whatever the order of the parameters, they are matched by their name.
41
42 **This library allows to invoke callables with named parameters in a generic and extensible way.**
43
44 ### Dependency injection
45
46 Anyone familiar with AngularJS is familiar with how dependency injection is performed:
47
48 ```js
49 angular.controller('MyController', ['dep1', 'dep2', function(dep1, dep2) {
50 // ...
51 }]);
52 ```
53
54 In PHP we find this pattern again in some frameworks and DI containers with partial to full support. For example in Silex you can type-hint the application to get it injected, but it only works with `Silex\Application`:
55
56 ```php
57 $app->get('/hello/{name}', function (Silex\Application $app, $name) {
58 // ...
59 });
60 ```
61
62 In Silly, it only works with `OutputInterface` to inject the application output:
63
64 ```php
65 $app->command('greet [name]', function ($name, OutputInterface $output) {
66 // ...
67 });
68 ```
69
70 [](http://php-di.org/doc/container.htmlPHP-DI](http://php-di.org/doc/container.html](http://php-di.org/doc/container.html) provides a way to invoke a callable and resolve all dependencies from the container using type-hints:
71
72 ```php
73 $container->call(function (Logger $logger, EntityManager $em) {
74 // ...
75 });
76 ```
77
78 **This library provides clear extension points to let frameworks implement any kind of dependency injection support they want.**
79
80 ### TL/DR
81
82 In short, this library is meant to be a base building block for calling a function with named parameters and/or dependency injection.
83
84 ## Installation
85
86 ```sh
87 $ composer require PHP-DI/invoker
88 ```
89
90 ## Usage
91
92 ### Default behavior
93
94 By default the `Invoker` can call using named parameters:
95
96 ```php
97 $invoker = new Invoker\Invoker;
98
99 $invoker->call(function () {
100 echo 'Hello world!';
101 });
102
103 // Simple parameter array
104 $invoker->call(function ($name) {
105 echo 'Hello ' . $name;
106 }, ['John']);
107
108 // Named parameters
109 $invoker->call(function ($name) {
110 echo 'Hello ' . $name;
111 }, [
112 'name' => 'John'
113 ]);
114
115 // Use the default value
116 $invoker->call(function ($name = 'world') {
117 echo 'Hello ' . $name;
118 });
119
120 // Invoke any PHP callable
121 $invoker->call(['MyClass', 'myStaticMethod']);
122
123 // Using Class::method syntax
124 $invoker->call('MyClass::myStaticMethod');
125 ```
126
127 Dependency injection in parameters is supported but needs to be configured with your container. Read on or jump to [](#built-in-support-for-dependency-injection*Built-in support for dependency injection*](#built-in-support-for-dependency-injection](#built-in-support-for-dependency-injection) if you are impatient.
128
129 Additionally, callables can also be resolved from your container. Read on or jump to [](#resolving-callables-from-a-container*Resolving callables from a container*](#resolving-callables-from-a-container](#resolving-callables-from-a-container) if you are impatient.
130
131 ### Parameter resolvers
132
133 Extending the behavior of the `Invoker` is easy and is done by implementing a [](https://github.com/PHP-DI/Invoker/blob/master/src/ParameterResolver/ParameterResolver.php`ParameterResolver`](https://github.com/PHP-DI/Invoker/blob/master/src/ParameterResolver/ParameterResolver.php](https://github.com/PHP-DI/Invoker/blob/master/src/ParameterResolver/ParameterResolver.php).
134
135 This is explained in details the [](doc/parameter-resolvers.mdParameter resolvers documentation](doc/parameter-resolvers.md](doc/parameter-resolvers.md).
136
137 #### Built-in support for dependency injection
138
139 Rather than have you re-implement support for dependency injection with different containers every time, this package ships with 2 optional resolvers:
140
141 - [](https://github.com/PHP-DI/Invoker/blob/master/src/ParameterResolver/Container/TypeHintContainerResolver.php`TypeHintContainerResolver`](https://github.com/PHP-DI/Invoker/blob/master/src/ParameterResolver/Container/TypeHintContainerResolver.php](https://github.com/PHP-DI/Invoker/blob/master/src/ParameterResolver/Container/TypeHintContainerResolver.php)
142
143 This resolver will inject container entries by searching for the class name using the type-hint:
144
145 ```php
146 $invoker->call(function (Psr\Logger\LoggerInterface $logger) {
147 // ...
148 });
149 ```
150
151 In this example it will `->get('Psr\Logger\LoggerInterface')` from the container and inject it.
152
153 This resolver is only useful if you store objects in your container using the class (or interface) name. Silex or Symfony for example store services under a custom name (e.g. `twig`, `db`, etc.) instead of the class name: in that case use the resolver shown below.
154
155 - [`ParameterNameContainerResolver`](https://github.com/PHP-DI/Invoker/blob/master/src/ParameterResolver/Container/ParameterNameContainerResolver.php)
156
157 This resolver will inject container entries by searching for the name of the parameter:
158
159 ```php
160 $invoker->call(function ($twig) {
161 // ...
162 });
163 ```
164
165 In this example it will `->get('twig')` from the container and inject it.
166
167 These resolvers can work with any dependency injection container compliant with [container-interop](https://github.com/container-interop/container-interop). If you container is not compliant you can use the [Acclimate](https://github.com/jeremeamia/acclimate-container) package.
168
169 Setting up those resolvers is simple:
170
171 ```php
172 // $container must be an instance of Interop\Container\ContainerInterface
173 $container = ...
174
175 $containerResolver = new TypeHintContainerResolver($container);
176 // or
177 $containerResolver = new ParameterNameContainerResolver($container);
178
179 $invoker = new Invoker\Invoker;
180 // Register it before all the other parameter resolvers
181 $invoker->getParameterResolver()->prependResolver($containerResolver);
182 ```
183
184 You can also register both resolvers at the same time if you wish by prepending both. Implementing support for more tricky things is easy and up to you!
185
186 ### Resolving callables from a container
187
188 The `Invoker` can be wired to your DI container to resolve the callables.
189
190 For example with an invokable class:
191
192 ```php
193 class MyHandler
194 {
195 public function __invoke()
196 {
197 // ...
198 }
199 }
200
201 // By default this doesn't work: an instance of the class should be provided
202 $invoker->call('MyHandler');
203
204 // If we set up the container to use
205 $invoker = new Invoker\Invoker(null, $container);
206 // Now 'MyHandler' is resolved using the container!
207 $invoker->call('MyHandler');
208 ```
209
210 The same works for a class method:
211
212 ```php
213 class WelcomeController
214 {
215 public function home()
216 {
217 // ...
218 }
219 }
220
221 // By default this doesn't work: home() is not a static method
222 $invoker->call(['WelcomeController', 'home']);
223
224 // If we set up the container to use
225 $invoker = new Invoker\Invoker(null, $container);
226 // Now 'WelcomeController' is resolved using the container!
227 $invoker->call(['WelcomeController', 'home']);
228 // Alternatively we can use the Class::method syntax
229 $invoker->call('WelcomeController::home');
230 ```
231
232 That feature can be used as the base building block for a framework's dispatcher.
233
234 Again, any [container-interop](https://github.com/container-interop/container-interop) compliant container can be provided, and [Acclimate](https://github.com/jeremeamia/acclimate-container) can be used for incompatible containers.
235