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

Commit 13f07a8

Browse files
committed
Merge pull request #29 from weierophinney/feature/invokable-configuration
Re-instate invokables
2 parents 34f42a8 + 617342b commit 13f07a8

File tree

3 files changed

+111
-76
lines changed

3 files changed

+111
-76
lines changed

doc/book/migration.md

Lines changed: 15 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -57,31 +57,10 @@ Configuration for v2 consisted of the following:
5757
]
5858
```
5959

60-
In v3, the configuration remains roughly the same, with the following changes:
60+
In v3, the configuration remains the same, with the following additions:
6161

6262
```php
6363
[
64-
'services' => [
65-
// service name => instance pairs
66-
],
67-
'aliases' => [
68-
// alias => service name pairs
69-
],
70-
'factories' => [
71-
// service name => factory pairs
72-
],
73-
'abstract_factories' => [
74-
// abstract factories
75-
],
76-
'initializers' => [
77-
// initializers
78-
],
79-
'delegators' => [
80-
// service name => [ delegator factories ]
81-
],
82-
'shared' => [
83-
// service name => boolean
84-
],
8564
'lazy_services' => [
8665
// The class_map is required if using lazy services:
8766
'class_map' => [
@@ -92,69 +71,29 @@ In v3, the configuration remains roughly the same, with the following changes:
9271
'proxies_target_dir' => 'path in which to write generated proxy classes',
9372
'write_proxy_files' => true, // boolean; false by default
9473
],
95-
'share_by_default' => boolean,
9674
]
9775
```
9876

99-
The main changes are that invokables no longer exist, and that lazy service
100-
configuration is now integrated.
77+
The main change is the addition of integrated lazy service configuration is now
78+
integrated.
10179

10280
### Invokables
10381

104-
*Invokables no longer exist.* As such, that key is no longer relevant. In each
105-
case, if the service name is also the name of the class, you can use the
106-
`InvokableFactory` and assign the service as a factory.
107-
108-
As an example, if you previously had the following configuration:
109-
110-
```php
111-
return [
112-
'invokables' => [
113-
'MyClass' => 'MyClass',
114-
],
115-
];
116-
```
117-
118-
You will now use the following:
119-
120-
```php
121-
use Zend\ServiceManager\Factory\InvokableFactory;
122-
123-
return [
124-
'factories' => [
125-
'MyClass' => InvokableFactory::class,
126-
],
127-
];
128-
```
129-
130-
What if you were using a service name that differed from the class name?
131-
132-
```php
133-
return [
134-
'invokables' => [
135-
'MyClass' => 'AnotherClass',
136-
],
137-
];
138-
```
139-
140-
In this case, you will create two separate entries: an invokable factory for the
141-
actual class, and an alias to it:
82+
*Invokables no longer exist,* at least, not identically to how they existed in
83+
ZF2.
14284

143-
```php
144-
use Zend\ServiceManager\Factory\InvokableFactory;
85+
Internally, `ServiceManager` now does the following for `invokables` entries:
14586

146-
return [
147-
'aliases' => [
148-
'MyClass' => 'AnotherClass',
149-
],
150-
'invokables' => [
151-
'AnotherClass' => InvokableFactory::class,
152-
],
153-
];
154-
```
87+
- If the name and value match, it creates a `factories` entry mapping the
88+
service name to `Zend\ServiceManager\Factory\InvokableFactory`.
89+
- If the name and value *do not* match, it creates an `aliases` entry mapping the
90+
service name to the class name, *and* a `factories` entry mapping the class
91+
name to `Zend\ServiceManager\Factory\InvokableFactory`.
15592

156-
Alternately, you can create a dedicated factory for `MyClass` that instantiates
157-
the correct class.
93+
This means that you can use your existing `invokables` configuration from
94+
version 2 in version 3. However, we recommend starting to update your
95+
configuration to remove `invokables` entries in favor of factories (and aliases,
96+
if needed).
15897

15998
### Lazy Services
16099

src/ServiceManager.php

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,10 @@ public function has($name, $checkAbstractFactories = false)
212212
* Valid top keys are:
213213
*
214214
* - services: service name => service instance pairs
215+
* - invokables: service name => class name pairs for classes that do not
216+
* have required constructor arguments; internally, maps the class to an
217+
* InvokableFactory instance, and creates an alias if the service name
218+
* and class name do not match.
215219
* - factories: service name => factory pairs; factories may be any
216220
* callable, string name resolving to an invokable class, or string name
217221
* resolving to a FactoryInterface instance.
@@ -245,6 +249,21 @@ protected function configure(array $config)
245249
$this->services = $config['services'] + $this->services;
246250
}
247251

252+
if (isset($config['invokables']) && ! empty($config['invokables'])) {
253+
$aliases = $this->createAliasesForInvokables($config['invokables']);
254+
$factories = $this->createFactoriesForInvokables($config['invokables']);
255+
256+
if (! empty($aliases)) {
257+
$config['aliases'] = (isset($config['aliases']))
258+
? array_merge($config['aliases'], $aliases)
259+
: $aliases;
260+
}
261+
262+
$config['factories'] = (isset($config['factories']))
263+
? array_merge($config['factories'], $factories)
264+
: $factories;
265+
}
266+
248267
if (isset($config['factories'])) {
249268
$this->factories = $config['factories'] + $this->factories;
250269
}
@@ -577,4 +596,50 @@ private function createLazyServiceDelegatorFactory()
577596

578597
return $this->lazyServicesDelegator;
579598
}
599+
600+
/**
601+
* Create aliases for invokable classes.
602+
*
603+
* If an invokable service name does not match the class it maps to, this
604+
* creates an alias to the class (which will later be mapped as an
605+
* invokable factory).
606+
*
607+
* @param array $invokables
608+
* @return array
609+
*/
610+
private function createAliasesForInvokables(array $invokables)
611+
{
612+
$aliases = [];
613+
foreach ($invokables as $name => $class) {
614+
if ($name === $class) {
615+
continue;
616+
}
617+
$aliases[$name] = $class;
618+
}
619+
return $aliases;
620+
}
621+
622+
/**
623+
* Create invokable factories for invokable classes.
624+
*
625+
* If an invokable service name does not match the class it maps to, this
626+
* creates an invokable factory entry for the class name; otherwise, it
627+
* creates an invokable factory for the entry name.
628+
*
629+
* @param array $invokables
630+
* @return array
631+
*/
632+
private function createFactoriesForInvokables(array $invokables)
633+
{
634+
$factories = [];
635+
foreach ($invokables as $name => $class) {
636+
if ($name === $class) {
637+
$factories[$name] = Factory\InvokableFactory::class;
638+
continue;
639+
}
640+
641+
$factories[$class] = Factory\InvokableFactory::class;
642+
}
643+
return $factories;
644+
}
580645
}

test/ServiceManagerTest.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,4 +148,35 @@ public function testShareability($sharedByDefault, $serviceShared, $serviceDefin
148148

149149
$this->assertEquals($shouldBeSameInstance, $a === $b);
150150
}
151+
152+
public function testMapsOneToOneInvokablesAsInvokableFactoriesInternally()
153+
{
154+
$config = [
155+
'invokables' => [
156+
InvokableObject::class => InvokableObject::class,
157+
],
158+
];
159+
160+
$serviceManager = new ServiceManager($config);
161+
$this->assertAttributeSame([
162+
InvokableObject::class => InvokableFactory::class,
163+
], 'factories', $serviceManager, 'Invokable object factory not found');
164+
}
165+
166+
public function testMapsNonSymmetricInvokablesAsAliasPlusInvokableFactory()
167+
{
168+
$config = [
169+
'invokables' => [
170+
'Invokable' => InvokableObject::class,
171+
],
172+
];
173+
174+
$serviceManager = new ServiceManager($config);
175+
$this->assertAttributeSame([
176+
'Invokable' => InvokableObject::class,
177+
], 'aliases', $serviceManager, 'Alias not found for non-symmetric invokable');
178+
$this->assertAttributeSame([
179+
InvokableObject::class => InvokableFactory::class,
180+
], 'factories', $serviceManager, 'Factory not found for non-symmetric invokable target');
181+
}
151182
}

0 commit comments

Comments
 (0)