@@ -372,6 +372,209 @@ will share identical locators amongst all the services referencing them::
372
372
373
373
.. _`Command pattern` : https://en.wikipedia.org/wiki/Command_pattern
374
374
375
+ Tagged Services Locator Collection with Index
376
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
377
+
378
+ If you want to retrieve a specific service within the injected service collector
379
+ you can use the ``index_by `` and ``default_index_method `` options of the argument
380
+ in combination with ``!tagged_locator `` to define an index.
381
+
382
+ In the following example, all services tagged with ``app.handler `` are passed as
383
+ first constructor argument to ``App\Handler\HandlerCollection ``,
384
+ but we can now access a specific injected service:
385
+
386
+ .. configuration-block ::
387
+
388
+ .. code-block :: yaml
389
+
390
+ # config/services.yaml
391
+ services :
392
+ App\Handler\One :
393
+ tags :
394
+ - { name: 'app.handler', key: 'handler_one' }
395
+
396
+ App\Handler\Two :
397
+ tags :
398
+ - { name: 'app.handler', key: 'handler_two' }
399
+
400
+ App\HandlerCollection :
401
+ # inject all services tagged with app.handler as first argument
402
+ arguments : [!tagged_locator { tag: 'app.handler', index_by: 'key' }]
403
+
404
+ .. code-block :: xml
405
+
406
+ <!-- config/services.xml -->
407
+ <?xml version =" 1.0" encoding =" UTF-8" ?>
408
+ <container xmlns =" http://symfony.com/schema/dic/services"
409
+ xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
410
+ xsi : schemaLocation =" http://symfony.com/schema/dic/services
411
+ http://symfony.com/schema/dic/services/services-1.0.xsd" >
412
+
413
+ <services >
414
+ <service id =" App\Handler\One" >
415
+ <tag name =" app.handler" key =" handler_one" />
416
+ </service >
417
+
418
+ <service id =" App\Handler\Two" >
419
+ <tag name =" app.handler" key =" handler_two" />
420
+ </service >
421
+
422
+ <service id =" App\HandlerCollection" >
423
+ <!-- inject all services tagged with app.handler as first argument -->
424
+ <argument type =" tagged_locator" tag =" app.handler" index-by =" key" />
425
+ </service >
426
+ </services >
427
+ </container >
428
+
429
+ .. code-block :: php
430
+
431
+ // config/services.php
432
+ use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
433
+ use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
434
+
435
+ $container->register(App\Handler\One::class)
436
+ ->addTag('app.handler', ['key' => 'handler_one']);
437
+
438
+ $container->register(App\Handler\Two::class)
439
+ ->addTag('app.handler', ['key' => 'handler_two']);
440
+
441
+ $container->register(App\Handler\HandlerCollection::class)
442
+ // inject all services tagged with app.handler as first argument
443
+ ->addArgument(new ServiceLocatorArgument(new TaggedIteratorArgument('app.handler', 'key')));
444
+
445
+ After compilation the ``HandlerCollection `` to retrieve a specific service by it's ``key `` attribute
446
+ from the service locator injected, we just have to do ``$serviceLocator->get('handler_two'); `` to
447
+ retrieve the ``handler_two `` handler::
448
+
449
+ // src/Handler/HandlerCollection.php
450
+ namespace App\Handler;
451
+
452
+ use Symfony\Component\DependencyInjection\ServiceLocator;
453
+
454
+ class HandlerCollection
455
+ {
456
+ public function __construct(ServiceLocator $locator)
457
+ {
458
+ $handlerTwo = $locator->get('handler_two'):
459
+ }
460
+ }
461
+ .. tip ::
462
+
463
+ You can omit the ``index_attribute_name `` attribute, by implementing a static
464
+ method ``getDefaultIndexAttributeName `` to the handler.
465
+
466
+ Based on the previous example ``App\Handler\One `` should look like this::
467
+
468
+ // src/Handler/One.php
469
+ namespace App\Handler;
470
+
471
+ class One
472
+ {
473
+ public static function getDefaultIndexName(): string
474
+ {
475
+ return 'handler_one';
476
+ }
477
+ }
478
+ And the configuration:
479
+
480
+ .. configuration-block ::
481
+
482
+ .. code-block :: yaml
483
+
484
+ # config/services.yaml
485
+ services :
486
+ App\Handler\One :
487
+ tags :
488
+ - { name: 'app.handler', priority: 20 }
489
+
490
+ # ...
491
+
492
+ .. code-block :: xml
493
+
494
+ <!-- config/services.xml -->
495
+ <?xml version =" 1.0" encoding =" UTF-8" ?>
496
+ <container xmlns =" http://symfony.com/schema/dic/services"
497
+ xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
498
+ xsi : schemaLocation =" http://symfony.com/schema/dic/services
499
+ http://symfony.com/schema/dic/services/services-1.0.xsd" >
500
+
501
+ <services >
502
+ <service id =" App\Handler\One" >
503
+ <tag name =" app.handler" priority =" 20" />
504
+ </service >
505
+
506
+ <!-- ... -->
507
+ </services >
508
+ </container >
509
+
510
+ .. code-block :: php
511
+
512
+ // config/services.php
513
+ $container->register(App\Handler\One::class)
514
+ ->addTag('app.handler', ['priority' => 20]);
515
+
516
+ // ...
517
+
518
+ You also can define the name of the static method to implement on each service
519
+ with the ``default_index_method `` attribute on the argument.
520
+
521
+ Based on the previous example ``App\Handler\One `` should look like::
522
+
523
+ // src/Handler/One.php
524
+ namespace App\Handler;
525
+
526
+ class One
527
+ {
528
+ public static function someFunctionName(): string
529
+ {
530
+ return 'handler_one';
531
+ }
532
+ }
533
+ And the configuration:
534
+
535
+ .. configuration-block ::
536
+
537
+ .. code-block :: yaml
538
+
539
+ # config/services.yaml
540
+ services :
541
+ # ...
542
+
543
+ App\HandlerCollection :
544
+ # inject all services tagged with app.handler as first argument
545
+ arguments : [!tagged_locator { tag: 'app.handler', index_by: 'key', default_index_method: 'someFunctionName' }]
546
+
547
+ .. code-block :: xml
548
+
549
+ <!-- config/services.xml -->
550
+ <?xml version =" 1.0" encoding =" UTF-8" ?>
551
+ <container xmlns =" http://symfony.com/schema/dic/services"
552
+ xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
553
+ xsi : schemaLocation =" http://symfony.com/schema/dic/services
554
+ http://symfony.com/schema/dic/services/services-1.0.xsd" >
555
+
556
+ <services >
557
+
558
+ <!-- ... --!>
559
+
560
+ <service id="App\HandlerCollection">
561
+ <!-- inject all services tagged with app.handler as first argument -->
562
+ <argument type =" tagged_locator" tag =" app.handler" index-by =" key" default-index-method =" someFunctionName" />
563
+ </service >
564
+ </services >
565
+ </container >
566
+
567
+ .. code-block :: php
568
+
569
+ // config/services.php
570
+ // ...
571
+
572
+ $container->register(App\HandlerCollection::class)
573
+ // inject all services tagged with app.handler as first argument
574
+ ->addArgument(new ServiceLocatorArgument(new TaggedIteratorArgument('app.handler', 'key', 'someFunctionName')));
575
+
576
+ See also :doc: `tagged services </service_container/tags >`
577
+
375
578
Service Subscriber Trait
376
579
------------------------
377
580
0 commit comments