1 | <?php |
||
12 | class ContainerFactory extends Configuration |
||
13 | { |
||
14 | 1 | public function __construct() |
|
16 | |||
17 | /** |
||
18 | * Register a component for dependency injection. |
||
19 | * |
||
20 | * There are numerous valid ways to register components. |
||
21 | * |
||
22 | * * `register(Foo::class)` registers a component by it's class-name, and will try to |
||
23 | * automatically resolve all of it's constructor arguments. |
||
24 | * |
||
25 | * * `register(Foo::class, ['bar'])` registers a component by it's class-name, and will |
||
26 | * use `'bar'` as the first constructor argument, and try to resolve the rest. |
||
27 | * |
||
28 | * * `register(Foo::class, [$container->ref(Bar::class)])` creates a boxed reference to |
||
29 | * a registered component `Bar` and provides that as the first argument. |
||
30 | * |
||
31 | * * `register(Foo::class, ['bat' => 'zap'])` registers a component by it's class-name |
||
32 | * and will use `'zap'` for the constructor argument named `$bat`, and try to resolve |
||
33 | * any other arguments. |
||
34 | * |
||
35 | * * `register(Bar::class, Foo::class)` registers a component `Foo` under another name |
||
36 | * `Bar`, which might be an interface or an abstract class. |
||
37 | * |
||
38 | * * `register(Bar::class, Foo::class, ['bar'])` same as above, but uses `'bar'` as the |
||
39 | * first argument. |
||
40 | * |
||
41 | * * `register(Bar::class, Foo::class, ['bat' => 'zap'])` same as above, but, well, guess. |
||
42 | * |
||
43 | * * `register(Bar::class, function (Foo $foo) { return new Bar(...); })` registers a |
||
44 | * component with a custom creation function. |
||
45 | * |
||
46 | * * `register(Bar::class, function ($name) { ... }, [$container->ref('db.name')]);` |
||
47 | * registers a component creation function with a reference to a component "db.name" |
||
48 | * as the first argument. |
||
49 | * |
||
50 | * In effect, you can think of `$func` as being an optional argument. |
||
51 | * |
||
52 | * The provided parameter values may include any `BoxedValueInterface`, such as the boxed |
||
53 | * component referenced created by {@see Container::ref()} - these will be unboxed as late |
||
54 | * as possible. |
||
55 | * |
||
56 | * @param string $name component name |
||
57 | * @param callable|mixed|mixed[]|null $func_or_map_or_type creation function or class-name, or, if the first |
||
58 | * argument is a class-name, a map of constructor arguments |
||
59 | * @param mixed|mixed[] $map mixed list/map of parameter values (and/or boxed values) |
||
60 | * |
||
61 | * @return void |
||
62 | * |
||
63 | * @throws ContainerException |
||
64 | */ |
||
65 | 1 | public function register($name, $func_or_map_or_type = null, $map = []) |
|
96 | |||
97 | /** |
||
98 | * Directly inject a component into the container - use this to register components that |
||
99 | * have already been created for some reason; for example, the Composer ClassLoader. |
||
100 | * |
||
101 | * @param string $name component name |
||
102 | * @param mixed $value |
||
103 | * |
||
104 | * @return void |
||
105 | * |
||
106 | * @throws ContainerException |
||
107 | */ |
||
108 | 1 | public function set($name, $value) |
|
114 | |||
115 | /** |
||
116 | * Register a component as an alias of another registered component. |
||
117 | * |
||
118 | * @param string $new_name new component name |
||
119 | * @param string $ref_name referenced existing component name |
||
120 | */ |
||
121 | public function alias($new_name, $ref_name) |
||
127 | |||
128 | /** |
||
129 | * Register a configuration function, which will be applied as late as possible, e.g. |
||
130 | * on first use of the component. For example: |
||
131 | * |
||
132 | * $factory->configure('stack', function (MiddlewareStack $stack) { |
||
133 | * $stack->push(new MoreAwesomeMiddleware()); |
||
134 | * }); |
||
135 | * |
||
136 | * The given configuration function should include the configured component as the |
||
137 | * first parameter to the closure, but may include any number of parameters, which |
||
138 | * will be resolved and injected. |
||
139 | * |
||
140 | * The first argument (component name) is optional - that is, the name can be inferred |
||
141 | * from a type-hint on the first parameter of the closure, so the following will work: |
||
142 | * |
||
143 | * $factory->register(PageLayout::class); |
||
144 | * |
||
145 | * $factory->configure(function (PageLayout $layout) { |
||
146 | * $layout->title = "Welcome"; |
||
147 | * }); |
||
148 | * |
||
149 | * In some cases, you may wish to fetch additional dependencies, by using additional |
||
150 | * arguments, and specifying how these should be resolved, e.g. using |
||
151 | * {@see Container::ref()} - for example: |
||
152 | * |
||
153 | * $factory->register("cache", FileCache::class); |
||
154 | * |
||
155 | * $factory->configure( |
||
156 | * "cache", |
||
157 | * function (FileCache $cache, $path) { |
||
158 | * $cache->setPath($path); |
||
159 | * }, |
||
160 | * ['path' => $container->ref('cache.path')] |
||
161 | * ); |
||
162 | * |
||
163 | * You can also use `configure()` to decorate objects, or manipulate (or replace) values: |
||
164 | * |
||
165 | * $factory->configure('num_kittens', function ($num_kittens) { |
||
166 | * return $num_kittens + 6; // add another litter |
||
167 | * }); |
||
168 | * |
||
169 | * In other words, if your closure returns something, the component will be replaced. |
||
170 | * |
||
171 | * @param string|callable $name_or_func component name |
||
172 | * (or callable, if name is left out) |
||
173 | * @param callable|mixed|mixed[] $func_or_map `function (Type $component, ...) : void` |
||
174 | * (or parameter values, if name is left out) |
||
175 | * @param mixed|mixed[] $map mixed list/map of parameter values and/or boxed values |
||
176 | * (or unused, if name is left out) |
||
177 | * |
||
178 | * @return void |
||
179 | * |
||
180 | * @throws ContainerException |
||
181 | */ |
||
182 | 1 | public function configure($name_or_func, $func_or_map = null, $map = []) |
|
213 | |||
214 | /** |
||
215 | * Creates a boxed reference to a component with a given name. |
||
216 | * |
||
217 | * You can use this in conjunction with `register()` to provide a component reference |
||
218 | * without expanding that reference until first use - for example: |
||
219 | * |
||
220 | * $factory->register(UserRepo::class, [$factory->ref('cache')]); |
||
221 | * |
||
222 | * This will reference the "cache" component and provide it as the first argument to the |
||
223 | * constructor of `UserRepo` - compared with using `$container->get('cache')`, this has |
||
224 | * the advantage of not actually activating the "cache" component until `UserRepo` is |
||
225 | * used for the first time. |
||
226 | * |
||
227 | * Another reason (besides performance) to use references, is to defer the reference: |
||
228 | * |
||
229 | * $factory->register(FileCache::class, ['root_path' => $factory->ref('cache.path')]); |
||
230 | * |
||
231 | * In this example, the component "cache.path" will be fetched from the container on |
||
232 | * first use of `FileCache`, giving you a chance to configure "cache.path" later. |
||
233 | * |
||
234 | * @param string $name component name |
||
235 | * |
||
236 | * @return BoxedReference component reference |
||
237 | */ |
||
238 | 1 | public function ref($name) |
|
242 | |||
243 | /** |
||
244 | * Add a packaged configuration (a "provider") to this container. |
||
245 | * |
||
246 | * @see ProviderInterface |
||
247 | * |
||
248 | * @param ProviderInterface $provider |
||
249 | * |
||
250 | * @return void |
||
251 | */ |
||
252 | 1 | public function add(ProviderInterface $provider) |
|
256 | |||
257 | /** |
||
258 | * Create and bootstrap a new `Container` instance |
||
259 | * |
||
260 | * @return Container |
||
261 | */ |
||
262 | 1 | public function createContainer() |
|
266 | } |
||
267 |