1: | <?php declare(strict_types=1); |
2: | |
3: | namespace Salient\Contract\Container; |
4: | |
5: | use Psr\Container\ContainerInterface as PsrContainerInterface; |
6: | use Salient\Contract\Core\Chainable; |
7: | use Salient\Contract\Core\Instantiable; |
8: | use Salient\Contract\Core\Unloadable; |
9: | |
10: | /** |
11: | * A service container with contextual bindings |
12: | * |
13: | * If a service resolves to a new instance of a class that implements |
14: | * `ContainerAwareInterface`, the container is passed to its |
15: | * {@see ContainerAwareInterface::setContainer()} method. |
16: | * |
17: | * Then, if the resolved instance implements {@see ServiceAwareInterface}, its |
18: | * {@see ServiceAwareInterface::setService()} method is called. |
19: | * |
20: | * A service provider registered via {@see provider()} or {@see providers()} may |
21: | * also implement any combination of the following interfaces: |
22: | * |
23: | * - {@see SingletonInterface} to be instantiated once per container |
24: | * - {@see HasServices} to specify which of its interfaces are services to |
25: | * register with the container |
26: | * - {@see HasBindings} to bind additional services to the container |
27: | * - {@see HasContextualBindings} to bind services to the container that only |
28: | * apply in the context of the provider |
29: | * |
30: | * {@see SingletonInterface} is ignored if a lifetime other than |
31: | * {@see ServiceLifetime::INHERIT} is given when the service provider is |
32: | * registered. |
33: | * |
34: | * @api |
35: | */ |
36: | interface ContainerInterface extends |
37: | PsrContainerInterface, |
38: | Chainable, |
39: | Instantiable, |
40: | Unloadable |
41: | { |
42: | /** |
43: | * Creates a new service container |
44: | */ |
45: | public function __construct(); |
46: | |
47: | /** |
48: | * Check if the global container is set |
49: | */ |
50: | public static function hasGlobalContainer(): bool; |
51: | |
52: | /** |
53: | * Get the global container, creating it if necessary |
54: | */ |
55: | public static function getGlobalContainer(): ContainerInterface; |
56: | |
57: | /** |
58: | * Set or unset the global container |
59: | */ |
60: | public static function setGlobalContainer(?ContainerInterface $container): void; |
61: | |
62: | /** |
63: | * Apply the contextual bindings of a service to a copy of the container |
64: | * |
65: | * @param class-string $id |
66: | * @return static |
67: | */ |
68: | public function inContextOf(string $id): ContainerInterface; |
69: | |
70: | /** |
71: | * Resolve a service from the container |
72: | * |
73: | * Values in `$args` are matched with service dependencies using one or more |
74: | * of the following strategies: |
75: | * |
76: | * - match objects to parameters by hinted type |
77: | * - match other values to parameters by name |
78: | * - match remaining values by type, then position |
79: | * |
80: | * @template T |
81: | * |
82: | * @param class-string<T> $id |
83: | * @param mixed[] $args |
84: | * @return T&object |
85: | * @throws ArgumentsNotUsedExceptionInterface if `$args` are given and `$id` |
86: | * resolves to a shared instance. |
87: | */ |
88: | public function get(string $id, array $args = []): object; |
89: | |
90: | /** |
91: | * Resolve a partially-resolved service from the container |
92: | * |
93: | * This method resolves `$id` normally but passes `$service` to |
94: | * {@see ServiceAwareInterface::setService()} instead of `$id`. |
95: | * |
96: | * @template T |
97: | * @template TService |
98: | * |
99: | * @param class-string<T> $id |
100: | * @param class-string<TService> $service |
101: | * @param mixed[] $args |
102: | * @return T&TService&object |
103: | * @throws ArgumentsNotUsedExceptionInterface if `$args` are given and `$id` |
104: | * resolves to a shared instance. |
105: | */ |
106: | public function getAs(string $id, string $service, array $args = []): object; |
107: | |
108: | /** |
109: | * Resolve a service to a concrete class name |
110: | * |
111: | * @template T |
112: | * |
113: | * @param class-string<T> $id |
114: | * @return class-string<T> |
115: | */ |
116: | public function getName(string $id): string; |
117: | |
118: | /** |
119: | * Check if a service is bound to the container |
120: | * |
121: | * @param class-string $id |
122: | */ |
123: | public function has(string $id): bool; |
124: | |
125: | /** |
126: | * Check if a shared service is bound to the container |
127: | * |
128: | * @param class-string $id |
129: | */ |
130: | public function hasSingleton(string $id): bool; |
131: | |
132: | /** |
133: | * Check if a service resolves to a shared instance |
134: | * |
135: | * @param class-string $id |
136: | */ |
137: | public function hasInstance(string $id): bool; |
138: | |
139: | /** |
140: | * Check if a service provider is registered with the container |
141: | * |
142: | * @param class-string $id |
143: | */ |
144: | public function hasProvider(string $id): bool; |
145: | |
146: | /** |
147: | * Bind a service to the container |
148: | * |
149: | * Subsequent requests for `$id` resolve to `$class`. |
150: | * |
151: | * If `$class` is `null`, `$id` resolves to itself. |
152: | * |
153: | * `$args` are merged with `$args` passed to {@see get()} or {@see getAs()} |
154: | * when `$id` resolves to a new instance of `$class`. |
155: | * |
156: | * @template TService |
157: | * @template T of TService |
158: | * |
159: | * @param class-string<TService> $id |
160: | * @param class-string<T>|null $class |
161: | * @param mixed[] $args |
162: | * @return $this |
163: | */ |
164: | public function bind( |
165: | string $id, |
166: | ?string $class = null, |
167: | array $args = [] |
168: | ): ContainerInterface; |
169: | |
170: | /** |
171: | * Bind a service to the container if it isn't already bound |
172: | * |
173: | * @template TService |
174: | * @template T of TService |
175: | * |
176: | * @param class-string<TService> $id |
177: | * @param class-string<T>|null $class |
178: | * @param mixed[] $args |
179: | * @return $this |
180: | */ |
181: | public function bindIf( |
182: | string $id, |
183: | ?string $class = null, |
184: | array $args = [] |
185: | ): ContainerInterface; |
186: | |
187: | /** |
188: | * Bind a shared service to the container |
189: | * |
190: | * Subsequent requests for `$id` resolve to the instance of `$class` created |
191: | * when `$id` is first requested. |
192: | * |
193: | * @template TService |
194: | * @template T of TService |
195: | * |
196: | * @param class-string<TService> $id |
197: | * @param class-string<T>|null $class |
198: | * @param mixed[] $args |
199: | * @return $this |
200: | */ |
201: | public function singleton( |
202: | string $id, |
203: | ?string $class = null, |
204: | array $args = [] |
205: | ): ContainerInterface; |
206: | |
207: | /** |
208: | * Bind a shared service to the container if it isn't already bound |
209: | * |
210: | * @template TService |
211: | * @template T of TService |
212: | * |
213: | * @param class-string<TService> $id |
214: | * @param class-string<T>|null $class |
215: | * @param mixed[] $args |
216: | * @return $this |
217: | */ |
218: | public function singletonIf( |
219: | string $id, |
220: | ?string $class = null, |
221: | array $args = [] |
222: | ): ContainerInterface; |
223: | |
224: | /** |
225: | * Bind a shared instance to the container |
226: | * |
227: | * @template TService |
228: | * @template T of TService |
229: | * |
230: | * @param class-string<TService> $id |
231: | * @param T&object $instance |
232: | * @return $this |
233: | */ |
234: | public function instance(string $id, $instance): ContainerInterface; |
235: | |
236: | /** |
237: | * Register a contextual binding with the container |
238: | * |
239: | * Subsequent requests from `$context` for `$dependency` resolve to |
240: | * `$value`. |
241: | * |
242: | * If `$dependency` starts with `'$'`, it is matched with dependencies of |
243: | * `$context` by constructor parameter name, otherwise it is matched by |
244: | * type. |
245: | * |
246: | * If `$value` is a callback, its return value is used. |
247: | * |
248: | * @template TValue |
249: | * |
250: | * @param class-string[]|class-string $context |
251: | * @param class-string<TValue>|string $dependency |
252: | * @param (callable(ContainerInterface): TValue)|class-string<TValue>|TValue $value |
253: | * @return $this |
254: | */ |
255: | public function addContextualBinding($context, string $dependency, $value): ContainerInterface; |
256: | |
257: | /** |
258: | * Register a service provider with the container, optionally specifying |
259: | * which of its services to bind or ignore |
260: | * |
261: | * For performance reasons, classes bound to the container with |
262: | * {@see bind()} or {@see singleton()} are not loaded until they are |
263: | * resolved. Classes registered with {@see provider()} are loaded |
264: | * immediately, but are not instantiated until they are resolved. |
265: | * |
266: | * @param class-string $id |
267: | * @param class-string[]|null $services Services to bind, or `null` to |
268: | * include all services. |
269: | * @param class-string[] $exceptServices Services to ignore. |
270: | * @param ServiceLifetime::* $lifetime |
271: | * @return $this |
272: | */ |
273: | public function provider( |
274: | string $id, |
275: | ?array $services = null, |
276: | array $exceptServices = [], |
277: | int $lifetime = ServiceLifetime::INHERIT |
278: | ): ContainerInterface; |
279: | |
280: | /** |
281: | * Register a service map with the container |
282: | * |
283: | * A service map is an array with entries that map a service (usually an |
284: | * interface) to a service provider (a class that extends or implements the |
285: | * service). |
286: | * |
287: | * Multiple services may be mapped to the same service provider, and service |
288: | * providers may be mapped to themselves. For example, to make `BarClass` |
289: | * discoverable via {@see ContainerInterface::getProviders()} whether it's |
290: | * bound to a service or not: |
291: | * |
292: | * ```php |
293: | * <?php |
294: | * $container->providers([ |
295: | * FooInterface::class => Env::get('foo_provider'), |
296: | * BarClass::class => BarClass::class, |
297: | * ]); |
298: | * ``` |
299: | * |
300: | * @param array<class-string,class-string> $serviceMap |
301: | * @param ServiceLifetime::* $lifetime |
302: | * @return $this |
303: | */ |
304: | public function providers( |
305: | array $serviceMap, |
306: | int $lifetime = ServiceLifetime::INHERIT |
307: | ): ContainerInterface; |
308: | |
309: | /** |
310: | * Get a list of service providers registered with the container |
311: | * |
312: | * @return array<class-string> |
313: | */ |
314: | public function getProviders(): array; |
315: | |
316: | /** |
317: | * Remove a binding from the container |
318: | * |
319: | * @param class-string $id |
320: | * @return $this |
321: | */ |
322: | public function unbind(string $id): ContainerInterface; |
323: | |
324: | /** |
325: | * Remove a shared instance from the container |
326: | * |
327: | * @param class-string $id |
328: | * @return $this |
329: | */ |
330: | public function removeInstance(string $id): ContainerInterface; |
331: | } |
332: |