Skip to content

Commit d51ca9e

Browse files
MartkCzdg
MartkCz
authored andcommitted
ContainerBuilder:resolveImplement supports polymorphism (#175)
1 parent ed14761 commit d51ca9e

File tree

3 files changed

+113
-1
lines changed

3 files changed

+113
-1
lines changed

src/DI/ContainerBuilder.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,8 @@ private function resolveImplement(ServiceDefinition $def, $name): void
417417
$hint = Reflection::getParameterType($param);
418418
if (isset($ctorParams[$param->getName()])) {
419419
$arg = $ctorParams[$param->getName()];
420-
if ($hint !== Reflection::getParameterType($arg)) {
420+
$argHint = Reflection::getParameterType($arg);
421+
if ($hint !== $argHint && !is_a($hint, $argHint, true)) {
421422
throw new ServiceCreationException("Type hint for \${$param->getName()} in $methodName doesn't match type hint in $class constructor.");
422423
}
423424
$def->getFactory()->arguments[$arg->getPosition()] = self::literal('$' . $arg->getName());
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
<?php
2+
3+
/**
4+
* Test: Nette\DI\Compiler: generated services factories from interfaces with class type hints in parameters.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
use Nette\DI;
10+
use Tester\Assert;
11+
12+
13+
require __DIR__ . '/../bootstrap.php';
14+
15+
interface IShape
16+
{
17+
public function getName(): string;
18+
}
19+
20+
class Circle implements IShape
21+
{
22+
public function getName(): string
23+
{
24+
return 'circle';
25+
}
26+
}
27+
28+
class Triangle implements IShape
29+
{
30+
public function getName(): string
31+
{
32+
return 'triangle';
33+
}
34+
}
35+
36+
class Ellipse extends Circle
37+
{
38+
public function getName(): string
39+
{
40+
return 'ellipse';
41+
}
42+
}
43+
44+
interface ICircleFactory
45+
{
46+
public function create(Circle $shape): Picture;
47+
}
48+
49+
interface ITriangleFactory
50+
{
51+
public function create(Triangle $shape): Picture;
52+
}
53+
54+
interface IEllipseFactory
55+
{
56+
public function create(Ellipse $shape): Picture;
57+
}
58+
59+
class Picture
60+
{
61+
public $shape;
62+
63+
64+
public function __construct(IShape $shape)
65+
{
66+
$this->shape = $shape;
67+
}
68+
69+
70+
public function getName(): string
71+
{
72+
return $this->shape->getName();
73+
}
74+
}
75+
76+
$compiler = new DI\Compiler;
77+
$container = createContainer($compiler, 'files/compiler.generatedFactory.polymorphism.neon');
78+
79+
Assert::type(ICircleFactory::class, $container->getService('circle'));
80+
$picture = $container->getService('circle')->create(new Circle);
81+
Assert::type(Picture::class, $picture);
82+
Assert::same('circle', $picture->getName());
83+
84+
Assert::type(ITriangleFactory::class, $container->getService('triangle'));
85+
$picture = $container->getService('triangle')->create(new Triangle);
86+
Assert::type(Picture::class, $picture);
87+
Assert::same('triangle', $picture->getName());
88+
89+
Assert::type(IEllipseFactory::class, $container->getService('ellipse'));
90+
$picture = $container->getService('ellipse')->create(new Ellipse);
91+
Assert::type(Picture::class, $picture);
92+
Assert::same('ellipse', $picture->getName());
93+
94+
Assert::type(ICircleFactory::class, $container->getService('circle'));
95+
$picture = $container->getService('circle')->create(new Ellipse);
96+
Assert::type(Picture::class, $picture);
97+
Assert::same('ellipse', $picture->getName());
98+
99+
Assert::throws(function () use ($container) {
100+
$container->getService('ellipse')->create(new Circle);
101+
}, TypeError::class);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
services:
2+
3+
circle:
4+
implement: ICircleFactory
5+
6+
triangle:
7+
implement: ITriangleFactory
8+
9+
ellipse:
10+
implement: IEllipseFactory

0 commit comments

Comments
 (0)