@@ -372,6 +372,218 @@ 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
+ .. code-block :: php
450
+
451
+ // src/Handler/HandlerCollection.php
452
+ namespace App\Handler;
453
+
454
+ use Symfony\Component\DependencyInjection\ServiceLocator;
455
+
456
+ class HandlerCollection
457
+ {
458
+ public function __construct(ServiceLocator $serviceLocator)
459
+ {
460
+ $handler_two = $serviceLocator->get('handler_two'):
461
+ }
462
+ }
463
+
464
+
465
+ .. tip ::
466
+
467
+ You can omit the ``index_attribute_name `` attribute, by implementing a static
468
+ method ``getDefaultIndexAttributeName `` to the handler.
469
+
470
+ Based on the previous example ``App\Handler\One `` should look like this:
471
+
472
+ .. code-block :: php
473
+
474
+ // src/Handler/One.php
475
+ namespace App\Handler;
476
+
477
+ class One
478
+ {
479
+ public static function getDefaultIndexName(): string
480
+ {
481
+ return 'handler_one';
482
+ }
483
+ }
484
+
485
+ And the configuration:
486
+
487
+ .. configuration-block ::
488
+
489
+ .. code-block :: yaml
490
+
491
+ # config/services.yaml
492
+ services :
493
+ App\Handler\One :
494
+ tags :
495
+ - { name: 'app.handler', priority: 20 }
496
+
497
+ # ...
498
+
499
+ .. code-block :: xml
500
+
501
+ <!-- config/services.xml -->
502
+ <?xml version =" 1.0" encoding =" UTF-8" ?>
503
+ <container xmlns =" http://symfony.com/schema/dic/services"
504
+ xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
505
+ xsi : schemaLocation =" http://symfony.com/schema/dic/services
506
+ http://symfony.com/schema/dic/services/services-1.0.xsd" >
507
+
508
+ <services >
509
+ <service id =" App\Handler\One" >
510
+ <tag name =" app.handler" priority =" 20" />
511
+ </service >
512
+
513
+ <!-- ... -->
514
+ </services >
515
+ </container >
516
+
517
+ .. code-block :: php
518
+
519
+ // config/services.php
520
+ $container->register(App\Handler\One::class)
521
+ ->addTag('app.handler', ['priority' => 20]);
522
+
523
+ // ...
524
+
525
+ You also can define the name of the static method to implement on each service
526
+ with the ``default_index_method `` attribute on the argument.
527
+
528
+ Based on the previous example ``App\Handler\One `` should look like :
529
+
530
+ .. code-block :: php
531
+
532
+ // src/Handler/One.php
533
+ namespace App\Handler;
534
+
535
+ class One
536
+ {
537
+ public static function someFunctionName(): string
538
+ {
539
+ return 'handler_one';
540
+ }
541
+ }
542
+
543
+ And the configuration:
544
+
545
+ .. configuration-block ::
546
+
547
+ .. code-block :: yaml
548
+
549
+ # config/services.yaml
550
+ services :
551
+ # ...
552
+
553
+ App\HandlerCollection :
554
+ # inject all services tagged with app.handler as first argument
555
+ arguments : [!tagged_locator { tag: 'app.handler', index_by: 'key', default_index_method: 'someFunctionName' }]
556
+
557
+ .. code-block :: xml
558
+
559
+ <!-- config/services.xml -->
560
+ <?xml version =" 1.0" encoding =" UTF-8" ?>
561
+ <container xmlns =" http://symfony.com/schema/dic/services"
562
+ xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
563
+ xsi : schemaLocation =" http://symfony.com/schema/dic/services
564
+ http://symfony.com/schema/dic/services/services-1.0.xsd" >
565
+
566
+ <services >
567
+
568
+ <!-- ... --!>
569
+
570
+ <service id="App\HandlerCollection">
571
+ <!-- inject all services tagged with app.handler as first argument -->
572
+ <argument type =" tagged_locator" tag =" app.handler" index-by =" key" default-index-method =" someFunctionName" />
573
+ </service >
574
+ </services >
575
+ </container >
576
+
577
+ .. code-block :: php
578
+
579
+ // config/services.php
580
+ // ...
581
+
582
+ $container->register(App\HandlerCollection::class)
583
+ // inject all services tagged with app.handler as first argument
584
+ ->addArgument(new ServiceLocatorArgument(new TaggedIteratorArgument('app.handler', 'key', 'someFunctionName')));
585
+ See also :doc: `tagged services </service_container/tags >`
586
+
375
587
Service Subscriber Trait
376
588
------------------------
377
589
0 commit comments