-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
Unset Composer's autoloader from the autoload stack #5834
Unset Composer's autoloader from the autoload stack #5834
Conversation
@@ -312,6 +312,7 @@ protected function discoverComposerNamespaces() | |||
$paths = $composer->getPrefixesPsr4(); | |||
$classes = $composer->getClassMap(); | |||
|
|||
$composer->unregister(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is in the discoverComposerNamespaces()
method.
So when $modules->discoverInComposer
is false, it does not run.
When $modules->discoverInComposer
is false, Composer autoloader is still enabled.
Is it intentional?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Composer's autoloader is only enabled when include
d in $this->discoverComposerNamespaces()
. In the code, once we include COMPOSER_PATH
, Composer will register its autoloader and prepend it in the autoload stack. If $modules->discoverInComposer
is false, then COMPOSER_PATH
is not included and won't be registered.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<?php
namespace App\Controllers;
use Closure;
class Home extends BaseController
{
public function index()
{
foreach (spl_autoload_functions() as $autoloader) {
switch ($autoloader) {
case $autoloader instanceof Closure:
echo get_class($autoloader) . PHP_EOL;
break;
case is_string($autoloader[0]):
echo $autoloader[0] . '::' . $autoloader[1] . PHP_EOL;
break;
case is_object($autoloader[0]):
echo get_class($autoloader[0]) . '::' . $autoloader[1] . PHP_EOL;
break;
}
}
}
}
With this PR, there is no Composer autoloader.
$ php public/index.php
CodeIgniter\Autoloader\Autoloader::loadClassmap
CodeIgniter\Autoloader\Autoloader::loadClass
PHPStan\PharAutoloader::loadClass
Closure
Next, make $discoverInComposer
false.
--- a/app/Config/Modules.php
+++ b/app/Config/Modules.php
@@ -29,7 +29,7 @@ class Modules extends BaseModules
*
* @var bool
*/
- public $discoverInComposer = true;
+ public $discoverInComposer = false;
/**
* --------------------------------------------------------------------------
$ php public/index.php
Composer\Autoload\ClassLoader::loadClass
CodeIgniter\Autoloader\Autoloader::loadClassmap
CodeIgniter\Autoloader\Autoloader::loadClass
PHPStan\PharAutoloader::loadClass
Closure
Composer autoloader is registered.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay. So there's a place in the application lifecycle where Composer is included regardless of the $discoverInComposer
flag. I'll take a look into it but most probably it shouldn't be included automatically.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Found it!
In system/bootstrap.php
and system/Test/bootstrap.php
, we require_once COMPOSER_PATH
regardless of the $discoverInComposer
flag, which shouldn't be the case as it is handled already in the Services::autoloader()->initialize()
call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (is_file(COMPOSER_PATH)) {
require_once COMPOSER_PATH;
}
When a user does not have Composer classmap (don't use So this PR is okay unless there is no bugs in the CI4 autoloader of PSR-4 class loading? |
@paulbalandan This is not directly related this PR, but I think the following logic is the cause of the error,
CodeIgniter4/system/CLI/Commands.php Lines 90 to 103 in 7107e78
|
Looks like good work and review underway already, let me know if you need me. |
|
136903c
to
85f7e69
Compare
@paulbalandan If you disable Auto-Discovery is the functionality to find automatically different type files like Command, Routes.php. $discoverInComposer means whether to find them in Composer PSR-4 namespaces. --- a/app/Config/Modules.php
+++ b/app/Config/Modules.php
@@ -29,7 +29,7 @@ class Modules extends BaseModules
*
* @var bool
*/
- public $discoverInComposer = true;
+ public $discoverInComposer = false;
/**
* -------------------------------------------------------------------------- --- a/app/Controllers/Home.php
+++ b/app/Controllers/Home.php
@@ -6,6 +6,6 @@ class Home extends BaseController
{
public function index()
{
- return view('welcome_message');
+ $faker = \Faker\Factory::create();
}
}
|
In my understanding, discovery in Composer means scanning all known directories and files to Composer - not just limited to those that can be found in Commands/, Routes/, Filters/, etc.
As such based on the above, discovery in Composer means registering all classes (whether or not those classes are CodeIgniter modules). If I'm not correct, then the implementing logic in |
@paulbalandan Okay, you think the error in #5834 (comment) is not a bug, and no problem. And I don't agree with it. @MGatner Can you give me your opinion? |
I think I'm not understanding something in these threads. Tell me what I have wrong here:
|
Maybe Events was a bad example because they aren't actually classes. But take Services - I should be able to do this regardless of settings in Config\Modules:
But if discovery is disabled in Config\Modules then this should fail:
|
Let me also add: from Paul's original description that it seems certain there are some things currently wrong with the implementation. |
Modules' "Auto-Discovery"( |
I agree with 1 and 3.
About 2. |
I sent another PR #5849. |
I have sent a PR to fix what appears to be a bug in Autoloader: #5850 |
Discussion continued on the bugfix PR. @paulbalandan Can you weigh in there? I think deciding on that (whether it is indeed a bug) will clarify the rest of these. |
#5850 was merged. So close this. |
Description
Fixes #5818 (comment)
Since we only need Composer to register its PSR4 namespaces and classmaps into our internal autoloader, it should not be in the
spl_autoload
stack after as this messes withclass_exists
checks. When our autoloader fails to find the file, PHP passes the search to the next autoloader, which is Composer. Our internal autoloader usesinclude_once
while Composer usesinclude
causing the redeclaration error.Cannot write a unit test for this. To check manually using this repo:
"App\\": "app"
in theautoload.psr4
section in the root composer.jsoncomposer dump -o
to regenerate the class map.'MyNameSpace' => APPPATH . 'ThirdParty/MyFolder'
inConfig\Autoload::$psr4
array.php spark make:command TeseCommand --namespace MyNameSpace
php spark
. This will now error.php spark
. No errors should appear.Checklist: