When using use
to import/alias namespace into current namespace in PHP - is it allowed to import to the name of a class that does exist in current namespace but isn‘t used in the current file?
PHP 5.6 and 7.x seem to behave differently here. Unfortunately, I couldn‘t figure out if it‘s allowed at all. If it were forbidden I‘d like my IDE to detect such collisions (because the code might break at any time again), otherwise it‘s a PHP bug in version 5.6.
See minimal code to get the idea:
src/Main/Bar.php:
namespace Cumuru\MinimalExample\Main;
class Bar { }
src/ToBeImported/Bar.php
namespace Cumuru\MinimalExample\ToBeImported;
class Bar { }
src/Main/Foo.php
namespace Cumuru\MinimalExample\Main;
use Cumuru\MinimalExample\ToBeImported\Bar;
class Foo { }
index.php
// [initialize autoloading]
// the following line breaks the code
$bar = new \Cumuru\MinimalExample\Main\Bar();
$foo = new \Cumuru\MinimalExample\Main\Foo();
This code will break in PHP 5.6 while it runs flawlessly in 7.1. Error message is
PHP Fatal error: Cannot use Cumuru\MinimalExample\ToBeImported\Bar as Bar because the name is already in use in .../src/Main/Foo.php on line 4
PHP Stack trace:
PHP 1. {main}() .../index.php:0
PHP 2. spl_autoload_call() .../index.php:6
PHP 3. Composer\Autoload\ClassLoader->loadClass() .../index.php:6
PHP 4. Composer\Autoload\includeFile() .../vendor/composer/ClassLoader.php:322
If you want to actually run the code see this github repo!
I was very lucky to detect the bug before deploying, it could have cost me ages to find it on our production system. I filed a bug report for my IDE but its priority was lowered stating it‘s a
bug in particular version in PHP which is outdated now
I wonder if this is true or if it‘s just an implementation detail of PHP 7 to handle imports on a per-file basis that might be changed in the future (making the code break again).
Edit:
I‘m aware of the possibility to alias class names via use Cumuru\MinimalExample\ToBeImported\Bar as ImportedBar;
.
My problem is what happens if class Cumuru\MinimalExample\Main\Bar
is created last, with both other classes being unchanged. Class Foo
will fatal then - if, and only if, class Cumuru\MinimalExample\Main\Bar
has been instantiated before class Foo
is loaded (in the same request / process).