- Issue created by @dpi
- ๐ฆ๐บAustralia dpi Perth, Australia
Critical points:
DrupalKernel
if (empty($this->moduleList) && !$this->containerNeedsRebuild) { $container_definition = $this->getCachedContainerDefinition(); }
and further down, where module PSR4 namespaces are added:
$this->attachSynthetic($container);
- ๐ฆ๐บAustralia dpi Perth, Australia
The result is similarly catastrophic for _simpler_ data types stored in the container, like enums.
Enums are a valid return type of getParameter() in Symfony, but Drupal has not been updated to support them.
- ๐บ๐ธUnited States cmlara
IIRX Iโve hit something similar, in the past.
IIRC I was trying to use a decorator with autowiring and an โignore if service doesnโt existโ attribute for an optional core service. However since the core module wasnโt loaded IIRC the references to the class caused similar faults.
Maybe thatโs not in scope here though I wonder if this will solve that too.
I wonder is this is a sign that Drupal should consider adopting a โmore standardโ composer layout of having modules always register their namespaces into the composer autoloader instead of the Kernel registering enabled modules?
Obviously adjusting the Kernel would make more sense here as an immediate fix, Iโm just spitballing โlong termโ if it might be time to let composer handle more of this.
- ๐ฌ๐งUnited Kingdom longwave UK
This does feel like another unfortunate side effect of Drupal making a distinction between a module being available on disk and a module that is actually installed.
- ๐ฆ๐บAustralia dpi Perth, Australia
I believe there is an issues somewhere..?
It would be nice to have code always-available, and simplify what "install" means. As in an "enabled" module (etc) adds it do discovery and namespaces, and which hooks are executed.
- ๐บ๐ธUnited States nicxvan
Would this be related ๐ฌ Drupal 11.2 upgrade causes \Drupal::$container is not initialized yet error Active
We're having trouble reproducing the issue. - ๐ณ๐ฟNew Zealand quietone
When I changed the version earlier, I did not add a comment. Doing that now.
If this problem was discovered on a version of Drupal that is not 11.x, add that information in the issue summary and leave the version at 11.x. In Drupal core changes are made on on 11.x (our main development branch) first, and are then back ported as needed according to the Core change policies โ . This is also mentioned on the version โ section of the list of issue fields documentation.
- ๐บ๐ธUnited States cmlara
I wonder if this will solve that too.
Thinking deeper my issue would likely not be solved by this solution. The module would still be disabled so code would still not exist in the auto loader even if the process occurred sooner.
I believe there is an issue(s) somewhere..?
I thought I saw something in the past, however on a quick search the only issue I turn up is #2536610: Ensure all modules are autoloaded with PSR-4 only if enabled โ advocating for the exact opposite.
- Merge request !12038Issue #3522410: Using instances of classes defined by modules in service container parameters causes fatal errors โ (Open) created by dpi
- ๐ฆ๐บAustralia dpi Perth, Australia
Pushed !12038
---
I've pushed up a PR which seems to fix the problem.
I'm at a loss for how to test this, as core/tests/bootstrap.php always adds all modules to the autoloader. I've tried a bunch of workarounds but I cant seem to get far. I'd appreciate if anyone can give that a go...
The flow of DrupalKernel has been moved around a bit, and the nearby type handling has been improved to satisfy PHPStan better, for even PHPStan levels core doesn't enforce yet. Especially with how core is passing around this semi-endorsed "container definition array" to various subsystems, for which I've specifically added a
@phpstan-type
for.The way the PR currently works is there is a new cache entry in
cache.container
cache bin with a cache key with a different prefix to the entry with the entire container definition array.A new
ContainerDiscovery
class is implemented to hold onto discovery related data. Objects beat arbitrary arrays. And we can extend it later if we need other discovery related things added to it.The flow of where
classLoaderAddMultiplePsr4</code. is called has been changed up. It isnt evident to me why <code>classLoaderAddMultiplePsr4
is currently inattachSynthetic
, and it doesnt look like its relevant to that method as state and namespaces are not modified there. Perhaps it was more relevant many refactors ago. So it has been moved out ofattachSynthetic
, up intoinitializeContainer
, so I can track and prevent doubling up of calls toclassLoaderAddMultiplePsr4
Some parts of DrupalKernel have been changed to be more concise especially when a "discovery" edition of a code block is introduced alongside an existing "container definition" block.
I'm at a loss for how to test this, as core/tests/bootstrap.php always adds all modules to the autoloader. I've tried a bunch of workarounds but I cant seem to get far. I'd appreciate if anyone can give that a go...
See
Drupal\Tests\migrate_drupal\Kernel\I18nQueryTraitTest::disablePsr4ForUninstalledModules()
for an idea on how this can be done, but it's only been used for a very limited test use case.- ๐ฆ๐บAustralia dpi Perth, Australia
Thanks for the suggestion @godotislate, however I don't think thats works.
Problem is I need to add an enum or class reference to the container then get a new kernel either by a new PHP process or programmatically _rebooting_ it, so DrupalKernel uses the warm container cache. However since the test is all the same process, PHP already knows the class exists and caches it (AFAICT), so modifying the autoloader after the fact wont work.
Perhaps I will need a web test since I can rely on fresh PHP processes...
However since the test is all the same process, PHP already knows the enum/class exists after I created instances of test enum/classes and caches it (AFAICT), so modifying the autoloader after the fact wont work.
Ah, right. Once the class/enum is loaded by PHP into memory, it stays there.
- ๐ฆ๐บAustralia dpi Perth, Australia
Converting what should be a Kernel test to a Functional test in order to get different PHP process is working out! ๐ Still open to ideas if anyone else knows better.
Coverage
Critically, an error is shown when the new
classLoaderAddMultiplePsr4
call in !12038 is removed:Exception: Warning: unserialize(): Class 'Drupal\autoloader_test\AutoloaderTestEnum' not found
Drupal\Component\Serialization\PhpSerialize::decode()() (Line: 21)When restored, the test pass once again.
NR
- ๐ฆ๐บAustralia dpi Perth, Australia
I did find ๐ Extension System, Part IV: Properly register all installed extensions/namespaces during container generation Needs work , which is more about comprehensive/unified namespaces for everything. E.g themes are added to autoloader in a crazy place (
\Drupal\Core\Extension\ThemeHandler::addTheme
). Distinctly different to this issue. - ๐บ๐ธUnited States nicxvan
I've been eyeing ๐ Extension System, Part IV: Properly register all installed extensions/namespaces during container generation Needs work because it's likely on the road to getting oop hooks in themes which will let us clean up a fair bit around preprocess.
- ๐บ๐ธUnited States nicxvan
I took a look, in general it looks like this is going in an interesting direction. I ran the test only job and it fails as expected.
I did not review the test.
Had a few questions.