|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2018-08-20 07:30 UTC] dirk dot gerigk at atraveo dot com
Description:
------------
I tried to merge some namespace classes into one file and found some strange behavior.
Questions:
- What are i'm missing to understand here? Or is that unexpected behavior?
- At witch time is what compiled and when is the global namespace executed?
- What effect has the use of an interface at the compile time?
- Why is the global namespace not executed as last?
However, the current behavior makes it impossible to merge classes into one file, but i thought that is possible because of namespaces.
'Fatal Error: Class '?\?' not found' is generated on the non working tests.
Test script:
---------------
#THIS WORKS
namespace X { class A extends B{} class B {} } namespace { new X\A; }
#THIS NOT
namespace { new X\A; } namespace X { class A extends B {} class B {} }
#THIS WORKS
namespace X { interface T {} class B implements T {} class A extends B {} }
namespace { new X\A; }
#THIS NOT
namespace X { class B implements T {} class A extends B {} interface T {} }
namespace { new X\A; }
#THIS WORKS NOT
namespace X { class A extends B {} class B implements T {} interface T {} }
#THIS ALSO WORKS NOT
namespace X { interface T {} class A extends B {} class B implements T {} }
#BUT THIS WORKS
namespace X { class B implements T {} class A extends B {} interface T {} }
#WORKS
namespace C { class A {} }
namespace { new X\A; }
namespace X { class A extends \C\A {} }
#WORKS NOT
namespace { new X\A; }
namespace X { class A extends \C\A {} }
namespace C { class A {} }
#WORKS AGAIN
namespace X { class A extends \C\A {} }
namespace { new X\A; }
namespace C { class A {} }
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sat Oct 25 21:00:01 2025 UTC |
As not for the first tests, if no interface is used and nothing extends nothing, the order of the of declaration can be random. So this works also fine: namespace { new X\A; } namespace X { class A {} } Make your one combinations to see the strange behavior.Your namespaces are not the problem: #THIS WORKS NOT class A extends B {} class B implements T {} interface T {} #THIS ALSO WORKS NOT interface T {} class A extends B {} class B implements T {} #BUT THIS WORKS class B implements T {} class A extends B {} interface T {} Or your last example: new A; class A {} Classes must be declared before they are instantiated/subclassed. http://www.php.net/language.oop5.inheritance I'm actually surprised that class B implements T {} class A extends B {} interface T {} works.But new A; class A {} should not work, because of 'Classes must be declared before they are instantiated/subclassed' And what is strange with namespaces that sometimes the behavior changes when interfaces are used, like this works namespace { new X\A; } namespace X { class B {} class A extends B {} } this not namespace { new X\A; } namespace X { interface T {} class B implements T {} class A extends B {} } In both examples the declaration is in the wrong order, but only the use of an interface breaks the code here. Whatever, i was only pointing to the strange behavior that makes it mostly impossible to merge complex namespaces in one file, when also a global namespace is present that instantiates objects. All examples here are simplified. How strange can it be when you are using classes that are extending and implementing from other namespaces. I came across it while i was merging code into one file. By the way i was just trying it for no real reason, just want to know if its possible. But thank for your comment> Classes must be declared before they are instantiated/subclassed. That's *mostly* true. More specifically, classes must be known to PHP before code tries to use them, however some class information is available after PHP initially parses a file and before it's done a more in-depth analysis. Defining classes in just about anything that uses {}s will disrupt that. https://3v4l.org/ZAEq1 But categorizing a namespace{} as one of the "anything that uses {}s" doesn't quite explain the reported behaviors.> That's *mostly* true. Indeed, there are some exceptions, but I would prefer to not overcomplicate the documentation, and also to leave some breathing room for future changes to the engine. After all, if code regards this simple rule, it should work in all circumstances (but see below). For instance, the first non-working example in the OP would have to be rewritten according to this rule to: namespace { new X\A; } namespace X { class B {} class A extends B {} } which would compile without errors[1]. > Classes must be declared before they are instantiated/subclassed. > http://www.php.net/language.oop5.inheritance Hmm, it seems the referenced man page does not say anything regarding instantiation, but rather speaks about extending classes and implementing interfaces, respectively. The former would only be relevant, if the class definition won't be resolved during compile time[2]. This is, however, basically the same for functions[3], so likely should be documented elsewhere (unless it already is). Not sure if the language specification[4] already addresses this. [1] <https://3v4l.org/UNvcS> [2] e.g. <https://3v4l.org/Xi4qg> [3] <https://3v4l.org/YSpRN> [4] <https://github.com/php/php-langspec>