New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cached ClassMap entries not reset after registering new prefix #5619
Comments
The However, what you are trying to do is currently not possible with the Composer autoloader. I cannot imagine a valid use-case for adding extra namespaces etc. on the fly. This is probably why the above situation is not supported. |
Test case would be: public function testAddPsr4ResetClassMap()
{
$loader = new ClassLoader();
$this->assertFalse($loader->findFile('ShinyVendor\ShinyPackage\SubNamespace\Foo'), "->findFile() finds class 'ShinyVendor\\ShinyPackage\\SubNamespace\\Foo'");
$loader->addPsr4('ShinyVendor\\ShinyPackage\\', __DIR__ . '/Fixtures');
$this->assertSame(__DIR__ . '/Fixtures', $loader->findFile('ShinyVendor\ShinyPackage\SubNamespace\Foo'));
} Fix could be something like: protected function resetClassMapAfterAdd($prefix)
{
foreach ($this->classMap as $class => $file) {
if (strpos($class, $prefix) === 0 && $file === false) {
unset($this->classMap[$class]);
}
}
foreach ($this->missingClasses as $class) {
if (strpos($class, $prefix) === 0) {
unset($this->missingClasses[$class]);
}
}
}
Well in the case of Nextcloud/ownCloud we only add the namespace once the app was loaded and we verified it should be enabled for the user. |
I do not understand your use-case. Since you already know what the user has access to (I presume you do, since you speak of verifying), you can just configure all of this properly up front. No need to do magic on the fly. |
Ah let me explain in a bit more detail then. We have an app that extends theming capabilities. We load theming capabilities on each request. But if you enable the new app we need to register some stuff. So it goes like: 1 We request theming It is an edge case I agree |
Why not just redirect the user after enabling it? A new request should start with a new autoloader and therefor properly pick up the changes. |
But why allow new prefixes to be added if you are not going to invalidate the cache? I get that from a performance perspective it is less ideal but maybe then a function to do it manually? Like flushMissingClasses? |
You are not supposed to modify the autoloader after you have registered it. |
@rullzer I'd suggest you create a new ClassLoader instance and register it as well (you can have two just fine). This isn't really a use case we want to support for performance reason IMO, adding a method to flush the cache would be an option but it's really just clutter for an edge case as registering a new classloader works just fine. |
Every system which allows stuff to be registered on the fly will have issues with this. I bet wordpress, typo3, Drupal on top of the example of nextcloud above. I'm wondering whether this should/could be really considered as an edge case. Note: The redirect workaround doesn't work in environment like automatic tests, where you simply have nothing like HTTP available. |
@dawehner see my last comment, this is working just fine for any use case IMO. |
Well, the singleton in |
What's wrong with |
Right, don't get me wrong I try to understand that. |
No what I said is.. keep using the existing loader, and just add a new one with the new classes you want to "activate".
Now you have two classloaders, one of which will handle the newly loaded module. |
The problem with adding new loaders is that we have services that use the canonical loader to find plugins provided by modules. Having multiple class loaders is not really an option for Drupal. |
class_exists() or Reflection is how you find classes though :/ |
Not in \Doctrine\Common\Reflection\StaticReflectionParser() it isn't :) |
@Seldaek what is the harm of clearing the negative caches in \Composer\Autoload\ClassLoader::$classMap after calling anything that adds to the ability of the class loader to find things? |
@alexpott the StaticReflectionParser should be initialized with a finder object dealing with all registered autoloaders then, not a single autoloader. And this is the responsibility of the code instantiating it. |
We use the composer autoloader to load our core classes. As well as load classes in enabled apps. For the core we generate a classmap. But the enabled apps are currently added on the fly by calling
$autoloader->addPsr4($prefix, $path)
.Now we have the following situation
This will result in an error because the autoloader has already cached and thus return false (see https://github.com/composer/composer/blob/master/src/Composer/Autoload/ClassLoader.php#L323)
I think it would make sense to clear all cached to false item that match the prefix. Since they might be there now.
The text was updated successfully, but these errors were encountered: