Skip to content

Commit bfbe003

Browse files
matej21dg
authored andcommitted
ContainerBuilder: better error message when class is not instantiable (#105)
1 parent 69b056e commit bfbe003

File tree

2 files changed

+36
-5
lines changed

2 files changed

+36
-5
lines changed

src/DI/ContainerBuilder.php

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -494,9 +494,14 @@ private function resolveEntityClass($entity, $recursive = [])
494494
return $this->definitions[$service]->getImplement() ?: $this->resolveServiceClass($service, $recursive);
495495

496496
} elseif (is_string($entity)) {
497-
if (!class_exists($entity) || !(new ReflectionClass($entity))->isInstantiable()) {
498-
$name = array_slice(array_keys($recursive), -1);
499-
throw new ServiceCreationException("Class $entity used in service '$name[0]' not found or is not instantiable.");
497+
$name = array_slice(array_keys($recursive), -1);
498+
if (!class_exists($entity)) {
499+
throw new ServiceCreationException("Class $entity used in service '$name[0]' not found.");
500+
} elseif ((new ReflectionClass($entity))->isAbstract()) {
501+
throw new ServiceCreationException("Class $entity used in service '$name[0]' is abstract.");
502+
} elseif (($rm = (new ReflectionClass($entity))->getConstructor()) !== NULL && !$rm->isPublic()) {
503+
$visibility = $rm->isProtected() ? 'protected' : 'private';
504+
throw new ServiceCreationException("Class $entity used in service '$name[0]' has $visibility constructor.");
500505
}
501506
return ltrim($entity, '\\');
502507
}

tests/DI/ContainerBuilder.factory.error.phpt

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@ Assert::exception(function () {
1515
$builder = new DI\ContainerBuilder;
1616
$builder->addDefinition('one')->setClass('X')->setFactory('Unknown');
1717
$builder->generateClasses();
18-
}, Nette\InvalidStateException::class, "Class Unknown used in service 'one' not found or is not instantiable.");
18+
}, Nette\InvalidStateException::class, "Class Unknown used in service 'one' not found.");
1919

2020

2121
Assert::exception(function () {
2222
$builder = new DI\ContainerBuilder;
2323
$builder->addDefinition('one')->setFactory('@two');
2424
$builder->addDefinition('two')->setFactory('Unknown');
2525
$builder->generateClasses();
26-
}, Nette\InvalidStateException::class, "Class Unknown used in service 'two' not found or is not instantiable.");
26+
}, Nette\InvalidStateException::class, "Class Unknown used in service 'two' not found.");
2727

2828

2929
Assert::exception(function () {
@@ -132,3 +132,29 @@ Assert::error(function () {
132132
$builder->addDefinition('one')->setFactory('Bad7::create');
133133
$builder->generateClasses();
134134
}, E_USER_NOTICE, "Type of service 'one' is unknown.");
135+
136+
137+
class Bad8
138+
{
139+
private function __construct()
140+
{}
141+
}
142+
143+
Assert::exception(function () {
144+
$builder = new DI\ContainerBuilder;
145+
$builder->addDefinition('one')->setClass('Bad8');
146+
$builder->generateClasses();
147+
}, Nette\InvalidStateException::class, "Class Bad8 used in service 'one' has private constructor.");
148+
149+
150+
abstract class Bad9
151+
{
152+
protected function __construct()
153+
{}
154+
}
155+
156+
Assert::exception(function () {
157+
$builder = new DI\ContainerBuilder;
158+
$builder->addDefinition('one')->setClass('Bad9');
159+
$builder->generateClasses();
160+
}, Nette\InvalidStateException::class, "Class Bad9 used in service 'one' is abstract.");

0 commit comments

Comments
 (0)