a.php
<?php
echo "AAA\n";
if(class_exists('NotImplementedException')) {
echo "BBB\n";
return;
echo "DDD\n";
}
echo "CCC\n";
/**
* Thrown when a feature is not yet implemented.
*/
class NotImplementedException extends Exception {}
b.php
<?php
include 'a.php';
include 'a.php';
When I run b.php I get:
AAA
BBB
PHP Fatal error: Cannot redeclare class NotImplementedException in /home/mark/Tests/IncludeTwice/a.php on line 15
What’s going on here? The output I would expect is
AAA
CCC
(class gets declared for first time)
AAA
BBB
(execution stops)
To those saying “the interpreter scans and parses the whole file first”: then why does this work?:
<?php
class A{}
if(!class_exists('A')) {
class A{}
}
I think one part is a bug…
The PHP interpreter works differently if you are extending a class.
This works:
This does not:
From what I can see in the PHP 5.4.0 source, there are two different functions that handle the binding of classes:
do_bind_class:4494for standalone classes anddo_bind_inherited_class:4533for inherited classes (ones that use the extend keyword).The stand-alone function has a conditional that ignores duplicate class definitions at compile time in case it is never hit at runtime. The inherited class version is missing this conditional (maybe on purpose, maybe not).
I would patch the inherited function to have the same conditional, test and submit to the developers.
And the other part is a feature…
As for your conditional class piece: I believe that PHP will load your class at compile-time if it is declared at global scope, but if it is contained inside a block, it will not be loaded until it is executed.
This works:
This doesn’t work, even though it is logically identical:
When you combine these two pieces of functionality, your problem arises since your class is both an inherited class and declared at global scope.