@@ -236,24 +236,76 @@ public function createService(string $name): object
236236 * Returns an instance of the autowired service of the given type. If it has not been created yet, it creates it.
237237 * @template T of object
238238 * @param class-string<T> $type
239+ * @param bool $throw throw exception if service doesn't exist?
239240 * @return ($throw is true ? T : ?T)
240241 * @throws MissingServiceException
241242 */
242243 public function getByType (string $ type , bool $ throw = true ): ?object
244+ {
245+ return $ this ->getByTypeAndTag ($ type , null , $ throw );
246+ }
247+
248+
249+ /**
250+ * Returns an instance of the autowired service of the given type and tag. If it has not been created yet, it creates it.
251+ * @template T of object
252+ * @param class-string<T> $type
253+ * @param bool $throw throw exception if service doesn't exist?
254+ * @return ($throw is true ? T : ?T)
255+ * @throws MissingServiceException
256+ */
257+ public function getByTypeAndTag (string $ type , ?string $ tag = null , bool $ throw = true ): ?object
243258 {
244259 $ type = Helpers::normalizeClass ($ type );
245260 if (!empty ($ this ->wiring [$ type ][0 ])) {
246- if (count ($ names = $ this ->wiring [$ type ][0 ]) === 1 ) {
247- return $ this ->getService ($ names [0 ]);
261+ $ names = $ this ->wiring [$ type ][0 ];
262+
263+ // Filter by tag if specified
264+ if ($ tag !== null ) {
265+ $ taggedNames = [];
266+ foreach ($ names as $ name ) {
267+ $ serviceTags = $ this ->findByTag ($ tag );
268+ if (isset ($ serviceTags [$ name ])) {
269+ $ taggedNames [] = $ name ;
270+ }
271+ }
272+ $ names = $ taggedNames ;
273+ }
274+
275+ // Try to find service with tag default
276+ if ($ tag === null && count ($ names ) > 1 ) {
277+ $ defaultTagNames = [];
278+ foreach ($ names as $ name ) {
279+ if (isset ($ this ->findByTag ('default ' )[$ name ])) {
280+ $ defaultTagNames [] = $ name ;
281+ }
282+ }
283+
284+ if ($ defaultTagNames !== []) {
285+ $ names = $ defaultTagNames ;
286+ }
248287 }
249288
250- natsort ($ names );
251- throw new MissingServiceException (sprintf ("Multiple services of type $ type found: %s. " , implode (', ' , $ names )));
289+ if (count ($ names ) === 1 ) {
290+ return $ this ->getService ($ names [0 ]);
291+ } elseif (count ($ names ) > 1 ) {
292+ natsort ($ names );
293+
294+ throw new MissingServiceException (sprintf (
295+ 'Multiple services of type %s%s found: %s. ' ,
296+ $ type ,
297+ $ tag !== null ? " with tag ' $ tag' " : '' ,
298+ implode (', ' , $ names ),
299+ ));
300+ }
301+ }
252302
253- } elseif ($ throw ) {
303+ if ($ throw ) {
254304 if (!class_exists ($ type ) && !interface_exists ($ type )) {
255305 throw new MissingServiceException (sprintf ("Service of type '%s' not found. Check the class name because it cannot be found. " , $ type ));
256- } elseif ($ this ->findByType ($ type )) {
306+ } elseif ($ tag !== null ) {
307+ throw new MissingServiceException (sprintf ("Service of type %s with tag '%s' not found. " , $ type , $ tag ));
308+ } elseif ($ this ->findByType ($ type ) !== []) {
257309 throw new MissingServiceException (sprintf ("Service of type %s is not autowired or is missing in di \u{a0}› \u{a0}export \u{a0}› \u{a0}types. " , $ type ));
258310 } else {
259311 throw new MissingServiceException (sprintf ('Service of type %s not found. Did you add it to configuration file? ' , $ type ));
@@ -363,7 +415,7 @@ public function callMethod(callable $function, array $args = []): mixed
363415 private function autowireArguments (\ReflectionFunctionAbstract $ function , array $ args = []): array
364416 {
365417 return Resolver::autowireArguments ($ function , $ args , fn (string $ type , bool $ single ) => $ single
366- ? $ this ->getByType ($ type )
418+ ? $ this ->getByType ($ type, throw: true )
367419 : array_map ($ this ->getService (...), $ this ->findAutowired ($ type )));
368420 }
369421
0 commit comments