Skip to content

Commit 3edc224

Browse files
[DI] dont mandate a class on inline services with a factory
1 parent 8ddf737 commit 3edc224

File tree

4 files changed

+20
-2
lines changed

4 files changed

+20
-2
lines changed

Compiler/CheckDefinitionValidityPass.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Symfony\Component\DependencyInjection\ContainerBuilder;
1515
use Symfony\Component\DependencyInjection\Exception\EnvParameterException;
1616
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
17+
use Symfony\Component\DependencyInjection\Loader\FileLoader;
1718

1819
/**
1920
* This pass validates each definition individually only taking the information
@@ -43,7 +44,7 @@ public function process(ContainerBuilder $container)
4344
}
4445

4546
// non-synthetic, non-abstract service has class
46-
if (!$definition->isAbstract() && !$definition->isSynthetic() && !$definition->getClass()) {
47+
if (!$definition->isAbstract() && !$definition->isSynthetic() && !$definition->getClass() && (!$definition->getFactory() || !preg_match(FileLoader::ANONYMOUS_ID_REGEXP, $id))) {
4748
if ($definition->getFactory()) {
4849
throw new RuntimeException(sprintf('Please add the class to service "%s" even if it is constructed by a factory since we might need to add method calls based on compile-time checks.', $id));
4950
}

Dumper/PhpDumper.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
use Symfony\Component\DependencyInjection\ExpressionLanguage;
3434
use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface as ProxyDumper;
3535
use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\NullDumper;
36+
use Symfony\Component\DependencyInjection\Loader\FileLoader;
3637
use Symfony\Component\DependencyInjection\Parameter;
3738
use Symfony\Component\DependencyInjection\Reference;
3839
use Symfony\Component\DependencyInjection\ServiceLocator as BaseServiceLocator;
@@ -1206,7 +1207,7 @@ private function addRemovedIds(): string
12061207
$ids = array_keys($ids);
12071208
sort($ids);
12081209
foreach ($ids as $id) {
1209-
if (preg_match('/^\.\d+_[^~]++~[._a-zA-Z\d]{7}$/', $id)) {
1210+
if (preg_match(FileLoader::ANONYMOUS_ID_REGEXP, $id)) {
12101211
continue;
12111212
}
12121213
$code .= ' '.$this->doExport($id)." => true,\n";

Loader/FileLoader.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
*/
2727
abstract class FileLoader extends BaseFileLoader
2828
{
29+
public const ANONYMOUS_ID_REGEXP = '/^\.\d+_[^~]++~[._a-zA-Z\d]{7}$/';
30+
2931
protected $container;
3032
protected $isLoadingInstanceof = false;
3133
protected $instanceof = [];

Tests/Compiler/CheckDefinitionValidityPassTest.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\DependencyInjection\Compiler\CheckDefinitionValidityPass;
1616
use Symfony\Component\DependencyInjection\ContainerBuilder;
17+
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
1718

1819
class CheckDefinitionValidityPassTest extends TestCase
1920
{
@@ -35,6 +36,19 @@ public function testProcessDetectsNonSyntheticNonAbstractDefinitionWithoutClass(
3536
$this->process($container);
3637
}
3738

39+
public function testProcessDetectsFactoryWithoutClass()
40+
{
41+
$container = new ContainerBuilder();
42+
43+
$container->register('.123_anonymous_service_id_should_not_throw_~1234567')->setFactory('factory');
44+
$this->process($container);
45+
46+
$this->expectException(RuntimeException::class);
47+
$container->register('.any_non_anonymous_id_throws')->setFactory('factory');
48+
49+
$this->process($container);
50+
}
51+
3852
public function testProcess()
3953
{
4054
$container = new ContainerBuilder();

0 commit comments

Comments
 (0)