1: <?php declare(strict_types=1);
2:
3: namespace Salient\Contract\Container;
4:
5: use Psr\Container\ContainerInterface as PsrContainerInterface;
6: use Salient\Contract\Container\Event\BeforeGlobalContainerSetEvent;
7: use Salient\Contract\Container\Exception\InvalidServiceException;
8: use Salient\Contract\Container\Exception\ServiceNotFoundException;
9: use Salient\Contract\Container\Exception\UnusedArgumentsException;
10: use Salient\Contract\Core\Chainable;
11: use Salient\Contract\Core\Instantiable;
12: use Salient\Contract\Core\Unloadable;
13: use Closure;
14:
15: /**
16: * @api
17: */
18: interface ContainerInterface extends
19: PsrContainerInterface,
20: Chainable,
21: Instantiable,
22: Unloadable,
23: HasServiceLifetime
24: {
25: /**
26: * Creates a new service container
27: */
28: public function __construct();
29:
30: /**
31: * Check if the global container is set
32: */
33: public static function hasGlobalContainer(): bool;
34:
35: /**
36: * Get the global container, creating it if necessary
37: */
38: public static function getGlobalContainer(): ContainerInterface;
39:
40: /**
41: * Set or unset the global container
42: *
43: * Dispatches {@see BeforeGlobalContainerSetEvent} if the global container
44: * will change.
45: */
46: public static function setGlobalContainer(?ContainerInterface $container): void;
47:
48: /**
49: * Apply contextual bindings to a copy of the container
50: *
51: * @param class-string $id
52: * @return static
53: */
54: public function inContextOf(string $id): ContainerInterface;
55:
56: /**
57: * Resolve a service from the container
58: *
59: * Values in `$args` are passed to constructor parameters after:
60: *
61: * 1. matching objects to parameters with compatible type declarations
62: * 2. matching keys in `$args` to parameters with the same name
63: * 3. matching values to parameters by type and position
64: *
65: * @template T
66: *
67: * @param class-string<T> $id
68: * @param mixed[] $args
69: * @return T&object
70: * @throws ServiceNotFoundException if `$id` is not instantiable.
71: * @throws UnusedArgumentsException if `$args` are given and `$id` resolves
72: * to a shared instance.
73: */
74: public function get(string $id, array $args = []): object;
75:
76: /**
77: * Resolve a partially-resolved service from the container
78: *
79: * `$id` is resolved normally, but `$service` is passed to
80: * {@see ServiceAwareInterface::setService()} instead of `$id`.
81: *
82: * @template TService
83: * @template T of TService
84: *
85: * @param class-string<T> $id
86: * @param class-string<TService> $service
87: * @param mixed[] $args
88: * @return T&object
89: * @throws ServiceNotFoundException if `$id` is not instantiable.
90: * @throws UnusedArgumentsException if `$args` are given and `$id` resolves
91: * to a shared instance.
92: */
93: public function getAs(string $id, string $service, array $args = []): object;
94:
95: /**
96: * Resolve a service from the container without returning an instance
97: *
98: * Returns the class name of the object {@see get()} would return.
99: *
100: * @template T
101: *
102: * @param class-string<T> $id
103: * @return class-string<T>
104: */
105: public function getClass(string $id): string;
106:
107: /**
108: * Check if a service is bound to the container
109: *
110: * @param class-string $id
111: */
112: public function has(string $id): bool;
113:
114: /**
115: * Check if a shared service or instance is bound to the container
116: *
117: * @param class-string $id
118: */
119: public function hasSingleton(string $id): bool;
120:
121: /**
122: * Check if a service resolves to a shared instance
123: *
124: * @param class-string $id
125: */
126: public function hasInstance(string $id): bool;
127:
128: /**
129: * Check if a service provider is registered with the container
130: *
131: * @param class-string $provider
132: */
133: public function hasProvider(string $provider): bool;
134:
135: /**
136: * Get a list of service providers registered with the container
137: *
138: * @return array<class-string>
139: */
140: public function getProviders(): array;
141:
142: /**
143: * Bind a service to the container
144: *
145: * Subsequent requests for `$id` resolve to an instance of `$class`, or
146: * `$id` if `$class` is `null`.
147: *
148: * If `$class` is a closure, it is called every time `$id` is resolved.
149: *
150: * @template TService
151: * @template T of TService
152: *
153: * @param class-string<TService> $id
154: * @param (Closure(self): T&object)|class-string<T>|null $class
155: * @return $this
156: */
157: public function bind(string $id, $class = null): ContainerInterface;
158:
159: /**
160: * Bind a service to the container if it isn't already bound
161: *
162: * @template TService
163: * @template T of TService
164: *
165: * @param class-string<TService> $id
166: * @param (Closure(self): T&object)|class-string<T>|null $class
167: * @return $this
168: */
169: public function bindIf(string $id, $class = null): ContainerInterface;
170:
171: /**
172: * Bind a shared service to the container
173: *
174: * Subsequent requests for `$id` resolve to the shared instance created when
175: * `$id` is first requested.
176: *
177: * @template TService
178: * @template T of TService
179: *
180: * @param class-string<TService> $id
181: * @param (Closure(self): T&object)|class-string<T>|null $class
182: * @return $this
183: */
184: public function singleton(string $id, $class = null): ContainerInterface;
185:
186: /**
187: * Bind a shared service to the container if it isn't already bound
188: *
189: * @template TService
190: * @template T of TService
191: *
192: * @param class-string<TService> $id
193: * @param (Closure(self): T&object)|class-string<T>|null $class
194: * @return $this
195: */
196: public function singletonIf(string $id, $class = null): ContainerInterface;
197:
198: /**
199: * Bind a shared instance to the container
200: *
201: * @template TService
202: * @template T of TService
203: *
204: * @param class-string<TService> $id
205: * @param T&object $instance
206: * @return $this
207: */
208: public function instance(string $id, object $instance): ContainerInterface;
209:
210: /**
211: * Remove a shared instance from the container
212: *
213: * @param class-string $id
214: * @return $this
215: */
216: public function removeInstance(string $id): ContainerInterface;
217:
218: /**
219: * Add a contextual binding to the container
220: *
221: * Subsequent requests for `$id` from the given contexts resolve to:
222: *
223: * - the return value of `$class` (if it is a closure)
224: * - an instance of `$class` (if it is a string)
225: * - `$class` itself (if it is an object), or
226: * - an instance of `$id` (if `$class` is `null`)
227: *
228: * If `$id` starts with `'$'`, it is matched with constructor parameters of
229: * the same name, and `$class` cannot be `null`.
230: *
231: * @template TService
232: * @template T of TService
233: *
234: * @param class-string[]|class-string $context
235: * @param class-string<TService>|non-empty-string $id
236: * @param (Closure(self): T&object)|class-string<T>|(T&object)|null $class
237: * @return $this
238: */
239: public function addContextualBinding(
240: $context,
241: string $id,
242: $class = null
243: ): ContainerInterface;
244:
245: /**
246: * Register a service provider with the container, optionally specifying
247: * which of its services to bind or ignore
248: *
249: * For performance reasons, classes bound to the container with
250: * {@see bind()} or {@see singleton()} are not loaded until they are
251: * resolved. Classes registered with {@see provider()} are loaded
252: * immediately to check for {@see HasServices}, {@see SingletonInterface}
253: * and other implementations.
254: *
255: * @param class-string $provider
256: * @param class-string[]|null $services Services of `$provider` to bind to
257: * the container, or `null` to bind every service returned by
258: * {@see HasServices::getServices()} (if implemented).
259: * @param class-string[] $excludeServices Services of `$provider` to exclude
260: * from binding.
261: * @param ContainerInterface::* $providerLifetime
262: * @return $this
263: * @throws InvalidServiceException if `$provider` returns invalid container
264: * bindings or doesn't provide one of the given `$services`.
265: */
266: public function provider(
267: string $provider,
268: ?array $services = null,
269: array $excludeServices = [],
270: int $providerLifetime = ContainerInterface::LIFETIME_INHERIT
271: ): ContainerInterface;
272:
273: /**
274: * Register an array that maps services (usually interfaces) to service
275: * providers (classes that extend or implement the mapped service)
276: *
277: * Multiple services may be mapped to the same service provider. Unmapped
278: * providers are mapped to themselves.
279: *
280: * @param array<class-string|int,class-string> $providers
281: * @param ContainerInterface::* $providerLifetime
282: * @return $this
283: */
284: public function providers(
285: array $providers,
286: int $providerLifetime = ContainerInterface::LIFETIME_INHERIT
287: ): ContainerInterface;
288: }
289: