Skip to content
This repository was archived by the owner on Feb 6, 2020. It is now read-only.

Commit 765c29a

Browse files
committed
Updated migration document
Updates the migration document to follow the proposed API.
1 parent e4e8cd5 commit 765c29a

File tree

1 file changed

+127
-89
lines changed

1 file changed

+127
-89
lines changed

doc/book/migration.md

Lines changed: 127 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -87,89 +87,16 @@ integrated.
8787

8888
### ConfigInterface
8989

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`..
16594

16695
### Config class
16796

16897
`Zend\ServiceManager\Config` has been updated to follow the changes to the
16998
`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.
173100

174101
## Invokables
175102

@@ -455,15 +382,15 @@ interface AbstractFactoryInterface extends FactoryInterface
455382
* @param string $requestedName
456383
* @return bool
457384
*/
458-
public function has(ContainerInterface $container, $requestedName);
385+
public function canCreate(ContainerInterface $container, $requestedName);
459386
}
460387
```
461388

462389
Note that it now *extends* the `FactoryInterface` (detailed below), and thus the
463390
factory logic has the same signature.
464391

465392
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
467394
arguments, the container and the requested service name.
468395

469396
### DelegatorFactoryInterface
@@ -601,9 +528,9 @@ In version 3, we define the following:
601528
- `Zend\ServiceManager\PluginManagerInterface`, which provides the public API
602529
differences from the `ServiceLocatorInterface`.
603530
- `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.)
607534

608535
### PluginManagerInterface
609536

@@ -622,15 +549,20 @@ extending `ServiceLocatorInterface` and adding one method:
622549
public function validate($instance);
623550
```
624551

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.
626556

627557
### AbstractPluginManager
628558

629559
As it did in version 2, `AbstractPluginManager` extends `ServiceManager`. **That
630560
means that all changes made to the `ServiceManager` for v3 also apply to the
631561
`AbstractPluginManager`.**
632562

633-
In addition, the following changes are also true for v3:
563+
In addition, review the following changes.
564+
565+
#### Constructor
634566

635567
- The constructor now accepts the following arguments, in the following order:
636568
- The parent container instance; this is usually the application-level
@@ -642,11 +574,35 @@ In addition, the following changes are also true for v3:
642574
a basic implementation (detailed below).
643575
- The signature of `get()` changes (more below).
644576

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:
646593

647594
```php
648595
public function validate($instance)
649596
{
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+
650606
if (empty($this->instanceOf) || $instance instanceof $this->instanceOf) {
651607
return;
652608
}
@@ -660,14 +616,23 @@ public function validate($instance)
660616
}
661617
```
662618

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:
666629

667630
```php
668631
protected $instanceOf = ValidatorInterface::class;
669632
```
670633

634+
#### get()
635+
671636
The `get()` signature changes from:
672637

673638
```php
@@ -683,6 +648,79 @@ public function get($name, array $options = null)
683648
Essentially: `$options` now *must* be an array if passed, and peering is no
684649
longer supported.
685650

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+
686724
### Plugin Service Creation
687725

688726
The `get()` method has new behavior:

0 commit comments

Comments
 (0)