Description
Symfony version(s) affected
6.4.16
Description
With Symfony\Component\DependencyInjection\Compiler\ResolveParameterPlaceHoldersPass::$skipScalars
set to true
(via patching),
#[Autowire(param: 'app.root')]
and #[Autowire('%app.root%')]
behave differently.
a. (wrong) #[Autowire(param: 'app.root')]
resolves the parameter at compile time, not taking $skipScalars === true
into account, breaking Drupal sites.
b. (Correct) #[Autowire('%app.root%')]
works as expected, taking $skipScalars === true
into account and resolves the parameter on service resolution.
How to reproduce
Change Symfony\Component\DependencyInjection\Compiler\ResolveParameterPlaceHoldersPass::$skipScalars
to be true
.
Create the following class and configure as autowired service:
class ParameterAutowireTestService {
public function __construct(
#[Autowire(param: 'test')] string $param1,
#[Autowire('%test%')] string $param2,
) {
if ($param1 !== $param2) {
throw new \Exception('$param1 and $param2 must be equal.');
}
}
}
Create a Symfony application with a test
parameter, which gets explicitly set with different values from a controller and a CLI command on every request.
Then retrieve the service from the container after the parameter has been set. The service should not throw the exception.
Possible Solution
No response
Additional Context
Drupal 10/11 has one parameter which can change between two single requests, especially between HTTP requests and CLI calls. This parameter app.root
holds the absolute path of the Drupal installation and this value is different on chrooted environments with open_basedir restrictions. For a detailed explanation why the path changes see Drupal Core 33482733 - Stop caching app.root and site.path in DI containter. Due to this, Drupal sets this parameter on the container on every request with the current value.
The problem is that parameters are resolved during container compilation and the compiled container definition gets cached by Drupal. As consequence when rebuilding the caches via CLI the HTTP requests use an invalid/unresolvable application root path path and vice versa causing lots of problems. After a long analysis and debugging session I found out that I can fix this by patching the Symfony\Component\DependencyInjection\Compiler\ResolveParameterPlaceHoldersPass
by enabling the $skipScalars
option.
When refactoring my module from function based hooks to OOP hooks (for upgrading to Drupal 11) I observed this patch not working anymore.