1

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).

undko
  • 927
  • 8
  • 15
  • I knocked together a stand-alone runnable version of that code - http://sandbox.onlinephpfunctions.com/code/5add0e29ad9ab049d46d7212d517e5077542db9d - and it errors the same on 5.6 and 7.1. It stands to reason as one ought not expect to be able to specify the same name for two different things. To get the code to work, Alias one of the BAr classes as something else, eg: use Cumuru\MinimalExample\ToBeImported\Bar as SomethingElse;. Can you show a *runnable* example of what you're seeing? – Adam Cameron Nov 06 '17 at 08:42
  • It seems to be important whether the classes are organized in seperate files. Again, a runnable example can be found on github: https://github.com/cumuru/minimal-example-namespace-collision. I‘m aware of the possibility to choose an alias when importing via `use`. The problem arises if class `Cumuru\MinimalExample\Main\Bar` is created last - I‘d have to (manually, no IDE support!) check all files in the same namespace for possible collisions. – undko Nov 06 '17 at 10:25
  • Yeah def see what you mean having installed yer example. I can't spot what yer doing wrong, sorry :-/ Have you checked the changelogs for php7 to see if anything sounds like it could be the cause of it? Might be able to work back from there as to what a fix on 5.6 might be. – Adam Cameron Nov 06 '17 at 13:17
  • Only related fix in PHP changelog I could find was https://bugs.php.net/bug.php?id=66773. But I think it‘s not related as the fatal shows up irrespective of opcache status. – undko Nov 06 '17 at 15:07

0 Answers0