@@ -87,89 +87,16 @@ integrated.
87
87
88
88
### ConfigInterface
89
89
90
- The ` ServiceManager ` is now immutable, meaning that you cannot configure it
91
- after-the-fact. If your ` ConfigInterface ` implementation called on the various
92
- methods for injecting new services, such as:
93
-
94
- - ` setService() `
95
- - ` setInvokableClass() `
96
- - ` setFactory() `
97
- - ` addAbstractFactory() `
98
- - ` addInitializer() `
99
- - ` addDelegator() `
100
-
101
- then you will need to alter the logic to instead aggregate a full configuration
102
- specification. This can then be passed to the ` ServiceManager ` instance's
103
- ` withConfig() ` method, which does the following:
104
-
105
- - Creates a clone of the manager.
106
- - Merges the incoming configuration with the current configuration within the
107
- clone.
108
- - Returns the clone.
109
-
110
- As such, your implementation should return the result of
111
- ` $serviceManager->withConfig() ` .
112
-
113
- As an example, consider this ` HelperConfig ` implementation from zend-i18n
114
- v2:
115
-
116
- ``` php
117
- class HelperConfig implements ConfigInterface
118
- {
119
- protected $invokables = [
120
- 'currencyformat' => 'Zend\I18n\View\Helper\CurrencyFormat',
121
- 'dateformat' => 'Zend\I18n\View\Helper\DateFormat',
122
- 'numberformat' => 'Zend\I18n\View\Helper\NumberFormat',
123
- 'plural' => 'Zend\I18n\View\Helper\Plural',
124
- 'translate' => 'Zend\I18n\View\Helper\Translate',
125
- 'translateplural' => 'Zend\I18n\View\Helper\TranslatePlural',
126
- ];
127
-
128
- public function configureServiceManager(ServiceManager $serviceManager)
129
- {
130
- foreach ($this->invokables as $name => $service) {
131
- $serviceManager->setInvokableClass($name, $service);
132
- }
133
- }
134
- }
135
- ```
136
-
137
- In version 3, this will become:
138
-
139
- ``` php
140
- use Interop\Container\ContainerInterface;
141
-
142
- class HelperConfig implements ConfigInterface
143
- {
144
- protected $invokables = [
145
- 'currencyformat' => 'Zend\I18n\View\Helper\CurrencyFormat',
146
- 'dateformat' => 'Zend\I18n\View\Helper\DateFormat',
147
- 'numberformat' => 'Zend\I18n\View\Helper\NumberFormat',
148
- 'plural' => 'Zend\I18n\View\Helper\Plural',
149
- 'translate' => 'Zend\I18n\View\Helper\Translate',
150
- 'translateplural' => 'Zend\I18n\View\Helper\TranslatePlural',
151
- ];
152
-
153
- public function configureServiceManager(ServiceManager $serviceManager)
154
- {
155
- return $serviceManager->withConfig([
156
- 'invokables' => $this->invokables,
157
- ]);
158
- }
159
- }
160
- ```
161
-
162
- Additionally, we have ** added** another method to ` ConfigInterface ` ,
163
- ` toArray() ` . This should return an array in a format that can be passed to the
164
- ` ServiceManager ` 's constructor or ` withConfig() ` method.
90
+ The principal change to the ` ConfigInterface ` is the addition of the
91
+ ` toArray() ` method. This method is intended to return a configuration array in
92
+ the format listed above, for passing to either the constructor or the
93
+ ` withConfig() ` method of the ` ServiceManager ` ..
165
94
166
95
### Config class
167
96
168
97
` Zend\ServiceManager\Config ` has been updated to follow the changes to the
169
98
` ConfigInterface ` and ` ServiceManager ` . This essentially means that it removes
170
- the various getter methods, and that the ` configureServiceManager() ` method
171
- instead aggregates the relevant configuration from the configuration passed to
172
- the constructor to pass to ` ServiceManager::withConfig() ` .
99
+ the various getter methods, and adds the ` toArray() ` method.
173
100
174
101
## Invokables
175
102
@@ -455,15 +382,15 @@ interface AbstractFactoryInterface extends FactoryInterface
455
382
* @param string $requestedName
456
383
* @return bool
457
384
*/
458
- public function has (ContainerInterface $container, $requestedName);
385
+ public function canCreate (ContainerInterface $container, $requestedName);
459
386
}
460
387
```
461
388
462
389
Note that it now * extends* the ` FactoryInterface ` (detailed below), and thus the
463
390
factory logic has the same signature.
464
391
465
392
In v2, the abstract factory defined the method ` canCreateServiceWithName() ` ; in
466
- v3, this is renamed to ` has ()` , and the method also now receives only two
393
+ v3, this is renamed to ` canCreate ()` , and the method also now receives only two
467
394
arguments, the container and the requested service name.
468
395
469
396
### DelegatorFactoryInterface
@@ -601,9 +528,9 @@ In version 3, we define the following:
601
528
- ` Zend\ServiceManager\PluginManagerInterface ` , which provides the public API
602
529
differences from the ` ServiceLocatorInterface ` .
603
530
- ` Zend\ServiceManager\AbstractPluginManager ` , which gives the basic
604
- capabilities for plugin managers. The class now has a * required* dependency on
605
- the application-level service manager instance, which is passed to all
606
- factories, abstract factories, etc.
531
+ capabilities for plugin managers. The class now has a (semi) * required*
532
+ dependency on the application-level service manager instance, which is passed
533
+ to all factories, abstract factories, etc. (More on this below.)
607
534
608
535
### PluginManagerInterface
609
536
@@ -622,15 +549,20 @@ extending `ServiceLocatorInterface` and adding one method:
622
549
public function validate($instance);
623
550
```
624
551
625
- All plugin managers * must* implement this interface.
552
+ All plugin managers * must* implement this interface. For backwards-compatibility
553
+ purposes, ` AbstractPluginManager ` will check for the ` validatePlugin() ` method
554
+ (defined as abstract in v2), and, on discovery, trigger an ` E_USER_DEPRECATED `
555
+ notice, followed by invocation of that method.
626
556
627
557
### AbstractPluginManager
628
558
629
559
As it did in version 2, ` AbstractPluginManager ` extends ` ServiceManager ` . ** That
630
560
means that all changes made to the ` ServiceManager ` for v3 also apply to the
631
561
` AbstractPluginManager ` .**
632
562
633
- In addition, the following changes are also true for v3:
563
+ In addition, review the following changes.
564
+
565
+ #### Constructor
634
566
635
567
- The constructor now accepts the following arguments, in the following order:
636
568
- The parent container instance; this is usually the application-level
@@ -642,11 +574,35 @@ In addition, the following changes are also true for v3:
642
574
a basic implementation (detailed below).
643
575
- The signature of ` get() ` changes (more below).
644
576
645
- ` validate() ` is defined as the following:
577
+ For backwards compatibility purposes, the constructor * also* allows the
578
+ following for the initial argument:
579
+
580
+ - A ` null ` value. In this case, the plugin manager will use itself as the
581
+ creation context, * but also raise a deprecation notice indicating a
582
+ container should be passed instead.* You can pass the parent container
583
+ to the ` setServiceLocator() ` method to reset the creation context, but,
584
+ again, this raises a deprecation notice.
585
+ - A ` ConfigInterface ` instance. In this case, the plugin manager will call
586
+ the config instance's ` toArray() ` method to cast it to an array, and use the
587
+ return value as the configuration to pass to the parent constructor. As with
588
+ the ` null ` value, the plugin manager will be set as its own creation context.
589
+
590
+ #### Validation
591
+
592
+ The ` validate() ` method is defined as follows:
646
593
647
594
``` php
648
595
public function validate($instance)
649
596
{
597
+ if (method_exists($this, 'validatePlugin')) {
598
+ trigger_error(sprintf(
599
+ '%s::validatePlugin() has been deprecated as of 3.0; please define validate() instead',
600
+ get_class($this)
601
+ ), E_USER_DEPRECATED);
602
+ $this->validatePlugin($instance);
603
+ return;
604
+ }
605
+
650
606
if (empty($this->instanceOf) || $instance instanceof $this->instanceOf) {
651
607
return;
652
608
}
@@ -660,14 +616,23 @@ public function validate($instance)
660
616
}
661
617
```
662
618
663
- Most plugin manager instances can therefore define the ` $instanceOf ` property to
664
- indicate what plugin interface is considered valid for the plugin manager, and
665
- make no further changes to the abstract plugin manager:
619
+ The two takeaways from this are:
620
+
621
+ - If you are upgrading from v2, your code should continue to work, * but will
622
+ emit a deprecation notice* . The way to remove the deprecation notice is to
623
+ rename the ` validatePlugin() ` method to ` validate() ` , or to remove it and
624
+ define the ` $instanceOf ` property (if all you're doing is checking the
625
+ plugin against a single typehint).
626
+ - Most plugin manager instances can simply define the ` $instanceOf ` property to
627
+ indicate what plugin interface is considered valid for the plugin manager, and
628
+ make no further changes to the abstract plugin manager:
666
629
667
630
``` php
668
631
protected $instanceOf = ValidatorInterface::class;
669
632
```
670
633
634
+ #### get()
635
+
671
636
The ` get() ` signature changes from:
672
637
673
638
``` php
@@ -683,6 +648,79 @@ public function get($name, array $options = null)
683
648
Essentially: ` $options ` now * must* be an array if passed, and peering is no
684
649
longer supported.
685
650
651
+ #### Deprecated methods
652
+
653
+ Finally, the following methods from v2's ` ServiceLocatorAwareInterface ` are
654
+ retained (without implementing the interface), but marked as deprecated:
655
+
656
+ - ` setServiceLocator() ` . This method exists as many tests and plugin manager
657
+ factories were using it to inject the parent locator (now called the creation
658
+ context). This method may still be used, and will now set the creation context
659
+ for the plugin manager, but also emit a deprecation warning.
660
+ - ` getServiceLocator() ` is implemented in ` ServiceManager ` (from which
661
+ ` AbstractPluginManager ` inherits), but marked as deprecated.
662
+
663
+ Regarding this latter point, ` getServiceLocator() ` exists to provide backwards
664
+ compatibility * for existing plugin factories* . These factories typically pull
665
+ dependencies from the parent/application container in order to initialize the
666
+ plugin. In v2, this would look like:
667
+
668
+ ``` php
669
+ function ($plugins)
670
+ {
671
+ $services = $plugins->getServiceLocator();
672
+
673
+ // pull dependencies from $services:
674
+ $foo = $services->get('Foo');
675
+ $bar = $services->get('Bar');
676
+
677
+ return new Plugin($foo, $bar);
678
+ }
679
+ ```
680
+
681
+ In v3, the initial argument to the factory is not the plugin manager instance,
682
+ but the * creation context* , which is analogous to the parent locator in v2. In
683
+ order to preserve existing behavior, we added the ` getServiceLocator() ` method
684
+ to the ` ServiceManager ` . As such, the above will continue to work in v3.
685
+
686
+ However, this method is marked as deprecated, and will emit an
687
+ ` E_USER_DEPRECATED ` notice. To remove the notice, you will need to upgrade your
688
+ code. The above example thus becomes:
689
+
690
+ ``` php
691
+ function ($services)
692
+ {
693
+ // pull dependencies from $services:
694
+ $foo = $services->get('Foo');
695
+ $bar = $services->get('Bar');
696
+
697
+ return new Plugin($foo, $bar);
698
+ }
699
+ ```
700
+
701
+ If you * were* using the passed plugin manager and pulling other plugins, you
702
+ will need to update your code to retrieve the plugin manager from the passed
703
+ container. As an example, given this:
704
+
705
+ ``` php
706
+ function ($plugins)
707
+ {
708
+ $anotherPlugin = $plugins->get('AnotherPlugin');
709
+ return new Plugin($anotherPlugin);
710
+ }
711
+ ```
712
+
713
+ You will need to rewrite it to:
714
+
715
+ ``` php
716
+ function ($services)
717
+ {
718
+ $plugins = $services->get('PluginManager');
719
+ $anotherPlugin = $plugins->get('AnotherPlugin');
720
+ return new Plugin($anotherPlugin);
721
+ }
722
+ ```
723
+
686
724
### Plugin Service Creation
687
725
688
726
The ` get() ` method has new behavior:
0 commit comments