File b.php
<?php
if(defined('Yes')) return;
define('Yes', 1);
function f(){
return 0;
}
?>
File a.php
<?php
include 'b.php';
include 'b.php';
?>
I expect the above code should not result an error. But, error message says function f is already defined.
But if b.php is modified like
<?php
if(!defined('Yes')){
define('Yes',1);
function f(){
return 0;
}
}?>
It works. What is this behaviour to be understood?
CodePudding user response:
PHP "looks ahead" for top-level function and class definitions, so that you can write code like this:
do_stuff();
do_more_stuff();
exit;
function do_stuff() {
// lots of code here
}
function do_more_stuff() {
// even more code
}
In order to do that, as soon as the file is compiled, function declarations are processed, and "forward declared", so that you don't get an "undefined function" error. In this example, the lines where the functions are declared are never even reached, but the declarations are processed at compile time, so it runs fine.
This is what happens in your first code: the function declaration is processed as soon as you include the file, before PHP even looks at the if statement.
However, when you put the whole block inside a condition like this ...
do_stuff();
do_more_stuff();
exit;
if ( true ) {
function do_stuff() {
// lots of code here
}
function do_more_stuff() {
// even more code
}
}
... the compiler spots that the declaration is conditional, and waits until that code is actually executed, when the run-time can check the condition. Even though the condition above is always true, the code gives an "undefined function" error, because the functions weren't declared yet when we tried to run them.
This is what happens in your second code: PHP waits until the if statement has run, and only declares the function when and if it reaches that line.
As an aside, this whole pattern of "if some constant is defined then exit" is very rare in PHP, because you can just use include_once
or require_once
, and it will handle it all for you.