Skip to content
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

Bug: defining new namespace under app/ causes Cannot declare class ..., because the name is already in use #5818

Closed
datamweb opened this issue Mar 21, 2022 · 13 comments · Fixed by #5824 or #5849
Labels
bug Verified issues on the current code behavior or pull requests that will fix them

Comments

@datamweb
Copy link
Contributor

datamweb commented Mar 21, 2022

PHP Version

8.0

CodeIgniter4 Version

v4.1.9

CodeIgniter4 Installation Method

Composer (using codeigniter4/appstarter)

Which operating systems have you tested for this bug?

Windows

Which server did you use?

apache

Database

--

What happened?

Problem in command php spark make:command --namespace MyNameSpace

Steps to Reproduce

composer create-project codeigniter4/appstarter project-root

    public $psr4 = [
        'MyNameSpace' 	        => APPPATH . 'ThirdParty\MyFolder',
    ];

php spark make:command --namespace MyNameSpace

Command class name : TeseCommand
File created: APPPATH\ThirdParty\MyFolder\Commands\TeseCommand.php

Everything is done well.
The corresponding file is created.
But now typing command php spark displays the following error!

PHP Fatal error:  Cannot declare class MyNameSpace\Commands\TeseCommand, because the name is already in use in P:\Program\xampp8010\htdocs\cimc\app\ThirdParty\MyFolder\Commands\TeseCommand.php on line 8

[ErrorException]

Cannot declare class MyNameSpace\Commands\TeseCommand, because the name is already in use

at APPPATH\ThirdParty\MyFolder\Commands\TeseCommand.php:8

Expected Output

@paulbalandan , @kenjis need to check to fix the problem. Please check.

Anything else?

This problem only exists in the installation method through composer .
This problem does not exist in the manual installation method.

@datamweb datamweb added the bug Verified issues on the current code behavior or pull requests that will fix them label Mar 21, 2022
@datamweb datamweb changed the title Bug: Bug: make:command --namespace Mar 21, 2022
@kenjis
Copy link
Member

kenjis commented Mar 21, 2022

Oh, amazing!

$ php spark

CodeIgniter v4.1.9 Command Line Tool - Server Time: 2022-03-21 18:58:37 UTC-05:00

PHP Fatal error:  Cannot declare class MyNameSpace\Commands\TeseCommand, because the name is already in use in /Users/kenji/work/codeigniter/tmp/project-root/app/ThirdParty/MyFolder/Commands/TeseCommand.php on line 8
PHP Stack trace:
PHP   1. {main}() /Users/kenji/work/codeigniter/tmp/project-root/spark:0
PHP   2. CodeIgniter\CLI\Console->run($useSafeOutput = *uninitialized*) /Users/kenji/work/codeigniter/tmp/project-root/spark:63
PHP   3. CodeIgniter\CodeIgniter->run($routes = *uninitialized*, $returnResponse = *uninitialized*) /Users/kenji/work/codeigniter/tmp/project-root/vendor/codeigniter4/framework/system/CLI/Console.php:48
PHP   4. CodeIgniter\CodeIgniter->handleRequest($routes = NULL, $cacheConfig = class Config\Cache { public $handler = 'file'; public $backupHandler = 'dummy'; public $storePath = '/Users/kenji/work/codeigniter/tmp/project-root/writable/cache/'; public $cacheQueryString = FALSE; public $prefix = ''; public $ttl = 60; public $reservedCharacters = '{}()/\\@:'; public $file = ['storePath' => '/Users/kenji/work/codeigniter/tmp/project-root/writable/cache/', 'mode' => 416]; public $memcached = ['host' => '127.0.0.1', 'port' => 11211, 'weight' => 1, 'raw' => FALSE]; public $redis = ['host' => '127.0.0.1', 'password' => NULL, 'port' => 6379, 'timeout' => 0, 'database' => 0]; public $validHandlers = ['dummy' => 'CodeIgniter\\Cache\\Handlers\\DummyHandler', 'file' => 'CodeIgniter\\Cache\\Handlers\\FileHandler', 'memcached' => 'CodeIgniter\\Cache\\Handlers\\MemcachedHandler', 'predis' => 'CodeIgniter\\Cache\\Handlers\\PredisHandler', 'redis' => 'CodeIgniter\\Cache\\Handlers\\RedisHandler', 'wincache' => 'CodeIgniter\\Cache\\Handlers\\WincacheHandler'] }, $returnResponse = FALSE) /Users/kenji/work/codeigniter/tmp/project-root/vendor/codeigniter4/framework/system/CodeIgniter.php:326
PHP   5. CodeIgniter\CodeIgniter->createController() /Users/kenji/work/codeigniter/tmp/project-root/vendor/codeigniter4/framework/system/CodeIgniter.php:410
PHP   6. CodeIgniter\CLI\CommandRunner->__construct() /Users/kenji/work/codeigniter/tmp/project-root/vendor/codeigniter4/framework/system/CodeIgniter.php:809
PHP   7. CodeIgniter\Config\BaseService::commands() /Users/kenji/work/codeigniter/tmp/project-root/vendor/codeigniter4/framework/system/CLI/CommandRunner.php:35
PHP   8. CodeIgniter\Config\BaseService::__callStatic($name = 'commands', $arguments = []) /Users/kenji/work/codeigniter/tmp/project-root/vendor/codeigniter4/framework/system/CLI/CommandRunner.php:35
PHP   9. CodeIgniter\Config\Services::commands($getShared = *uninitialized*) /Users/kenji/work/codeigniter/tmp/project-root/vendor/codeigniter4/framework/system/Config/BaseService.php:248
PHP  10. CodeIgniter\Config\BaseService::getSharedInstance($key = 'commands') /Users/kenji/work/codeigniter/tmp/project-root/vendor/codeigniter4/framework/system/Config/Services.php:150
PHP  11. CodeIgniter\Config\BaseService::commands(FALSE) /Users/kenji/work/codeigniter/tmp/project-root/vendor/codeigniter4/framework/system/Config/BaseService.php:189
PHP  12. CodeIgniter\Config\BaseService::__callStatic($name = 'commands', $arguments = [0 => FALSE]) /Users/kenji/work/codeigniter/tmp/project-root/vendor/codeigniter4/framework/system/Config/BaseService.php:189
PHP  13. CodeIgniter\Config\Services::commands($getShared = FALSE) /Users/kenji/work/codeigniter/tmp/project-root/vendor/codeigniter4/framework/system/Config/BaseService.php:248
PHP  14. CodeIgniter\CLI\Commands->__construct($logger = *uninitialized*) /Users/kenji/work/codeigniter/tmp/project-root/vendor/codeigniter4/framework/system/Config/Services.php:153
PHP  15. CodeIgniter\CLI\Commands->discoverCommands() /Users/kenji/work/codeigniter/tmp/project-root/vendor/codeigniter4/framework/system/CLI/Commands.php:46
PHP  16. CodeIgniter\Autoloader\FileLocator->findQualifiedNameFromPath($path = '/Users/kenji/work/codeigniter/tmp/project-root/app/ThirdParty/MyFolder/Commands/TeseCommand.php') /Users/kenji/work/codeigniter/tmp/project-root/vendor/codeigniter4/framework/system/CLI/Commands.php:99
PHP  17. class_exists($class = '\\App\\ThirdParty\\MyFolder\\Commands\\TeseCommand') /Users/kenji/work/codeigniter/tmp/project-root/vendor/codeigniter4/framework/system/Autoloader/FileLocator.php:280
PHP  18. Composer\Autoload\ClassLoader->loadClass($class = 'App\\ThirdParty\\MyFolder\\Commands\\TeseCommand') /Users/kenji/work/codeigniter/tmp/project-root/vendor/codeigniter4/framework/system/Autoloader/FileLocator.php:280
PHP  19. Composer\Autoload\includeFile($file = '/Users/kenji/work/codeigniter/tmp/project-root/vendor/composer/../../app/ThirdParty/MyFolder/Commands/TeseCommand.php') /Users/kenji/work/codeigniter/tmp/project-root/vendor/composer/ClassLoader.php:428
PHP  20. include() /Users/kenji/work/codeigniter/tmp/project-root/vendor/composer/ClassLoader.php:571

[ErrorException]

Cannot declare class MyNameSpace\Commands\TeseCommand, because the name is already in use

at APPPATH/ThirdParty/MyFolder/Commands/TeseCommand.php:8
$ git diff
diff --git a/app/Config/Autoload.php b/app/Config/Autoload.php
index ee27e3b..f2ed2a3 100644
--- a/app/Config/Autoload.php
+++ b/app/Config/Autoload.php
@@ -43,6 +43,7 @@ class Autoload extends AutoloadConfig
     public $psr4 = [
         APP_NAMESPACE => APPPATH, // For custom app namespace
         'Config'      => APPPATH . 'Config',
+        'MyNameSpace' => APPPATH . 'ThirdParty/MyFolder',
     ];
 
     /**

@kenjis kenjis removed the bug Verified issues on the current code behavior or pull requests that will fix them label Mar 22, 2022
@kenjis
Copy link
Member

kenjis commented Mar 22, 2022

This is because of #3423

Try:

--- a/composer.json
+++ b/composer.json
@@ -18,8 +18,6 @@
     },
     "autoload": {
         "psr-4": {
-            "App\\": "app",
-            "Config\\": "app/Config"
         },
         "exclude-from-classmap": [
             "**/Database/Migrations/**"
$ composer dump-autoload
$ php spark

@kenjis
Copy link
Member

kenjis commented Mar 22, 2022

I think this is misconfiguration.
Because 'MyNameSpace' is under App namespace.
The command file is autoloadable as App\ThirdParty\MyFolder\Commands\TeseCommand,
and the error occurs.

I recommend you change the location of the folder,
e.g. 'MyNameSpace' => ROOTPATH . 'MyFolder',.

@kenjis kenjis changed the title Bug: make:command --namespace Bug: make:command --namespace causes Cannot declare class ..., because the name is already in use Mar 22, 2022
@kenjis kenjis changed the title Bug: make:command --namespace causes Cannot declare class ..., because the name is already in use Bug: make:command --namespace causes Cannot declare class ..., because the name is already in use Mar 22, 2022
@datamweb
Copy link
Contributor Author

This is because of #3423

Try:

--- a/composer.json
+++ b/composer.json
@@ -18,8 +18,6 @@
     },
     "autoload": {
         "psr-4": {
-            "App\\": "app",
-            "Config\\": "app/Config"
         },
         "exclude-from-classmap": [
             "**/Database/Migrations/**"
$ composer dump-autoload
$ php spark

With this method, the error was temporarily solved.

@datamweb
Copy link
Contributor Author

I think this is misconfiguration. Because 'MyNameSpace' is under App namespace. The command file is autoloadable as App\ThirdParty\MyFolder\Commands\TeseCommand, and the error occurs.

I recommend you change the location of the folder, e.g. 'MyNameSpace' => ROOTPATH . 'MyFolder',.

@kenjis ,thank you for your review and response.
I set 'MyNameSpace' => ROOTPATH . 'MyFolder', and an error is not displayed.
I do not think this is an interesting solution. Because usually the packages must be installed as follows.
'Michalsn\Uuid' => APPPATH. 'ThirdParty/codeigniter4-uuid/src',
'Myth\Auth' => APPPATH .'ThirdParty/myth-auth/src',
and ...
Is this the final solution? Or will it be fixed in the future?

@kenjis
Copy link
Member

kenjis commented Mar 22, 2022

Because usually the packages must be installed as follows.
'Michalsn\Uuid' => APPPATH. 'ThirdParty/codeigniter4-uuid/src',
'Myth\Auth' => APPPATH .'ThirdParty/myth-auth/src',

Why do you think so?
All Composer packages are installed in vendor/.

If you really want to install in APPPATH .'ThirdParty/***,
remove App in autoload in composer.json like above. It works.

Is this the final solution? Or will it be fixed in the future?

At least, now I don't know there is a way to fix.

@datamweb
Copy link
Contributor Author

datamweb commented Mar 22, 2022

Because usually the packages must be installed as follows.
'Michalsn\Uuid' => APPPATH. 'ThirdParty/codeigniter4-uuid/src',
'Myth\Auth' => APPPATH .'ThirdParty/myth-auth/src',

Why do you think so? All Composer packages are installed in vendor/.

If you really want to install in APPPATH .'ThirdParty/***, remove App in autoload in composer.json like above. It works.

Because each package can be installed in two ways.
Composer.
Manually.
This error is displayed for people who installed Codigniter through Composer but installed my package manually.
And I have to force them to go through the above solution.
This is not good.

Is this the final solution? Or will it be fixed in the future?

At least, now I don't know there is a way to fix.

Thank you for your answer.

@omeco4christ
Copy link

I think this is misconfiguration. Because 'MyNameSpace' is under App namespace. The command file is autoloadable as App\ThirdParty\MyFolder\Commands\TeseCommand, and the error occurs.

I recommend you change the location of the folder, e.g. 'MyNameSpace' => ROOTPATH . 'MyFolder',.

I don't think this is an effective solution!

@paulbalandan
Copy link
Member

#3423 has been causing problems lately. I think we should revisit this.

I agree with @datamweb that using either composer or manual should pose no issues in installation or use. #3423 is inclined to the composer way, thereby restricting manual installation usage.

The solutions presented to both problems (including this one) caused by the change are both removing the autoload.psr4 section in composer.json. This is a clear sign that the change is not effective in the first place. Thus, it is necessary to remove it completely.

@kenjis kenjis changed the title Bug: make:command --namespace causes Cannot declare class ..., because the name is already in use Bug: defining new namespace under app/ causes Cannot declare class ..., because the name is already in use Mar 23, 2022
@kenjis kenjis added the bug Verified issues on the current code behavior or pull requests that will fix them label Mar 23, 2022
@kenjis
Copy link
Member

kenjis commented Mar 23, 2022

@paulbalandan
Okay, #3423 causes problems and there seems no benefit for most users,
let's revert it for now.

kenjis added a commit to kenjis/CodeIgniter4 that referenced this issue Mar 23, 2022
…ser.json

Revert codeigniter4#3423

Problems:
- Cannot change `app` folder name. Because the composer's path overwrite the config in Config\Autoload.
- Causes error when defining new namespace under app/. See codeigniter4#5818
@kenjis
Copy link
Member

kenjis commented Mar 23, 2022

I sent a PR to revet: #5824

I think now this issue is because of a bug in CI4 CLI\Commands.
See https://github.com/codeigniter4/CodeIgniter4/pull/5824/files#diff-b6175596618dbe61fe2d949e48bc9ba4b581d6bfb6f317644257a43485e1d4e4R80

@paulbalandan
Copy link
Member

Can you show a failing test case where CLI\Commands is failing. Sorry, but at first glance I cannot understand what the problem is.

@kenjis
Copy link
Member

kenjis commented Mar 24, 2022

Can't write test code.

  1. CodeIgniter\Autoloader\FileLocator->findQualifiedNameFromPath('.../app/ThirdParty/MyFolder/Commands/TeseCommand.php') finds '\\App\\ThirdParty\\MyFolder\\Commands\\TeseCommand' first, because App is prefered.
  2. class_exists('\App\ThirdParty\MyFolder\Commands\TeseCommand') calls CI4 autoloader and include_once('.../app/ThirdParty/MyFolder/Commands/TeseCommand.php')
  3. But '\App\ThirdParty\MyFolder\Commands\TeseCommand' does not exists.
  4. So Composer autoloader searches it and include '.../app/ThirdParty/MyFolder/Commands/TeseCommand.php'
  5. The file is included again and causes the error.

PHP 15. CodeIgniter\CLI\Commands->discoverCommands() /Users/kenji/work/codeigniter/tmp/project-root/vendor/codeigniter4/framework/system/CLI/Commands.php:46
PHP 16. CodeIgniter\Autoloader\FileLocator->findQualifiedNameFromPath($path = '/Users/kenji/work/codeigniter/tmp/project-root/app/ThirdParty/MyFolder/Commands/TeseCommand.php') /Users/kenji/work/codeigniter/tmp/project-root/vendor/codeigniter4/framework/system/CLI/Commands.php:99
PHP 17. class_exists($class = '\App\ThirdParty\MyFolder\Commands\TeseCommand') /Users/kenji/work/codeigniter/tmp/project-root/vendor/codeigniter4/framework/system/Autoloader/FileLocator.php:280
PHP 18. Composer\Autoload\ClassLoader->loadClass($class = 'App\ThirdParty\MyFolder\Commands\TeseCommand') /Users/kenji/work/codeigniter/tmp/project-root/vendor/codeigniter4/framework/system/Autoloader/FileLocator.php:280
PHP 19. Composer\Autoload\includeFile($file = '/Users/kenji/work/codeigniter/tmp/project-root/vendor/composer/../../app/ThirdParty/MyFolder/Commands/TeseCommand.php') /Users/kenji/work/codeigniter/tmp/project-root/vendor/composer/ClassLoader.php:428

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Verified issues on the current code behavior or pull requests that will fix them
Projects
None yet
4 participants