It appears that PHP normally requires nested functions to be defined before usage. But code built dynamically with require doesn't have the same restriction. Can anyone explain why the inconsistency?
EDIT: Just to clarify, what I want to understand is: why does example 2 work instead of failing like example 1?
Example 1
If this is the contents of file nested1.php:
<?php
function outer() {
inner();
function inner() {
print "Hello world.\n";
}
}
outer();
?>
Running this with php nested1.php returns:
PHP Fatal error: Call to undefined function inner() in nested1.php on line 3
However, if you move the inner() function call below the function definition like this:
<?php
function outer() {
function inner() {
print "Hello world.\n";
}
inner();
}
outer();
?>
and run again you get:
Hello world.
Example 2
If this is the contents of nested2.php:
<?php
function outer() {
require "inner.php";
}
outer();
?>
And this is the contents of inner.php:
<?php
inner();
function inner() {
print "Hello world.\n";
}
?>
Running this with php nested2.php returns:
Hello world.
When outer() function is called first time, the inner() function inside of it will get declared in global scope.
function outer() {
function inner() {
print "Hello world.\n";
}
inner();
}
outer();
outer();//Second call
Thus you'll get the following error:
Fatal error: Cannot redeclare inner()
because the second call to outer() tried to re declare inner() function.
In order to avoid this issue, you need to use anonymous function declaration like following:
function outer() {
$inner = function () {
print "Hello world.\n";
};
$inner();
}
outer();
outer();
In this case $inner available only in local function "outer" scope
Example 1:
PHP does not support nested functions. It only supports inner functions.
Nested function reference
Inner function reference
<?php
function outer() {
inner();
function inner() {
print "Hello world.\n";
}
}
outer();
Example 2: In this function you are just requiring file which includes and evaluates the scripts. Reference
<?php
function outer() {
require "inner.php";
}
outer();
?>
<?php
inner();
function inner() {
print "Hello world.\n";
}
?>
In your first example, you are trying to define a new function inside another function, but nested functions are not allowed by php. Doing something like this would be fine:
<?php
function outer() {
inner();
}
outer();
function inner() {
print "Hello world.\n";
}
?>
In your 2nd example, you are including a file. As you are not using nested functions in inner.php, the code works as expected.
Related
Example 1: Here I expect that function hello must be in the global scope.
But as per my expectation it does not behave same.It does not put function hello into global scope. at run time php must put function hello into global scope. It says undefined function hello().
$fruit=true;
foo();
hello();
function foo()
{
echo "you are in the foo<br/>";
}
if($fruit)
{
function hello()
{
echo "you are in the hello<br/>";
}
}
Example 2 : Now as after example 1 , i supposed the below script must also work as example 1. i supposed it will give also error undefined function bar(). But now here it behave differently and execute bar.
foo();
bar();
function foo()
{
function bar()
{
echo "I don't exist until foo() is called.\n";
}
}
So i am unable to get the concept how php interpreter behave internally. How does it parse the program, and does it execute the step one by one , or whole program at once?
I quote a manual for you:
When a function is defined in a conditional manner .... Its definition must be processed prior to being called.
And more:
All functions and classes in PHP have the global scope - they can be called outside a function even if they were defined inside and vice versa.
Example One:
You do not define the function hello() until a part of the script has run, its in an IF and therefore does not get defined until after you attempt to call it
Like this you get no errors as the IF is run before the now defined funtion hello is called. And of corse either way it is in the GLOBAL scope. But your way it didnt exist anywhere until after you called it.
<?php
$fruit=true;
if($fruit)
{
function hello()
{
echo "you are in the hello<br/>";
}
}
foo();
hello();
function foo()
{
echo "you are in the foo<br/>";
}
Not sure if this is due to a module I have installed or not, I've tried to remove all the extensions I have but this still doesn't work:
//test1.php
if(defined("TEST1")) {
return;
}
define("TEST1",1);
function test() {}
//test2.php
if(defined("TEST1")) {
return;
}
define("TEST1",1);
function test() {}
//test.php
include_once('test1.php');
include_once('test2.php');
test();
Results in a duplicate definition error. It looks like other checks like function_exists will work, but it's a bit messier to use.
According to PHP documentation (http://php.net/manual/en/functions.user-defined.php):
Functions need not be defined before they are referenced, except when a function is conditionally defined
It means that if you don't put your test() function into conditional statement it will be defined BEFORE script execution start.
To allow referencing functions that are defined further in the code, PHP at first searches the file for function (classes, etc) definitions, then runs the code. So when you're doing your:
if(defined('TEST1')) return;
Te function already exists and dupplicate error is triggered. The solution is to put them in any conditional statement (it does not have to make sense) or even just in braces. Functions defined in that manner will not be defined before script execution and also you won't be able to use them befere they are defined. You can fix your code just by doing this:
//test1.php
if(defined("TEST1")) {
return;
}
define("TEST1",1);
{
function test() {}
}
//test2.php
if(defined("TEST1")) {
return;
}
define("TEST1",1);
{
function test() {}
}
//test.php
include_once('test1.php');
include_once('test2.php');
test();
To test the behavior you can play with that two code snippets. This one will work:
<?php
test();
function test() {
echo 'Hello world!';
}
But this will fail with undefined function:
<?php
test();
{
function test() {
echo 'Hello world!';
}
}
While this again will work:
<?php
{
function test() {
echo 'Hello world!';
}
}
test();
Try
//test1.php
if(!defined("TEST1")) {
define("TEST1",1);
function test() {}
}
//test2.php
if(!defined("TEST1")) {
define("TEST1",1);
function test() {}
}
//test.php
include_once('test1.php');
include_once('test2.php');
test();
This is a snippet from my original code I am testing to handle error.
The FIRST approach is calling the fatalErrorHandler(), but the SECOND approach is not calling the fatalErrorHandler(). What could be the reason?
FIRST
<?php
//error_reporting(0);
function fatalErrorHandler() {
echo 'YAY IT WORKED';
}
# Registering shutdown function
register_shutdown_function('fatalErrorHandler');
// let force a Fatal error -- function does not exist
functiontest();
echo "hello";
?>
output:
Fatal error: Call to undefined function functiontest() in ...test2.php
on line 12 YAY IT WORKED
SECOND
<?php
//error_reporting(0);
function fatalErrorHandler() {
echo 'YAY IT WORKED';
}
# Registering shutdown function
register_shutdown_function('fatalErrorHandler');
// let force a Fatal error -- function does not exist
functiontest();
function foo () {
}
function foo() {
}
echo "hello";
?>
Output:
Fatal error: Cannot redeclare foo() (previously declared in
...test/test2.php:16) in ../test2.php on line 20
fatalErrorHandler is not getting called in this scenario. why?
In PHP you can use a function before you define it. I think this means that the interpreter must parse all functions before it starts execution. So register_shutdown_function is not yet called when this error is detected.
You could test this by moving the duplicate function definition into a separate file and including it with include or require.
I think it's about compiling order. See the condition.
Take a look at this example:
// The shutdown function won't be called
register_shutdown_function(function(){
echo "I'm in!";
});
function test(){}
function test(){}
And now at this example:
// The shutdown function will be called
register_shutdown_function(function(){
echo "I'm in!";
});
function test(){}
if(1 === 1)
{
function test(){}
}
I am really very surprised to see my function comes out to be undefined on AJAX request. I am wondering does function order matters in AJAX file? Following code will show you my problem -
This is the ajax.php file which is called by jquery/ajax request from index.php. It is supposed to simply print the name -
<?php
if(isset($_POST))
{
$name = 'admin';
echo display_name($name);
function display_name($name)
{
return $name;
}
}
?>
But when this file is called, i get -
Fatal error: Call to undefined function display_name()
But when i change the order of code i.e. function like this -
<?php
if(isset($_POST))
{
$name = 'admin';
function display_name($name)
{
return $name;
}
echo display_name($name);
}
?>
then it displays -
admin
How strange it is!
Thus if really function availability order matters then how the following code works -
It is simple file and it is NOT called by AJAX request. I am simply loading the file and doesn't matter where the function is written. It is working by all using any order of line code -
<?php
$name = 'admin';
echo display_name($name);
function display_name($name)
{
return $name;
}
?>
The following snippet is also working -
<?php
$name = 'admin';
function display_name($name)
{
return $name;
}
echo display_name($name);
?>
So please tell my the reason behind this difference. In page loading code works and on ajax request it doesn't. Why the function display_name() is undefined if it exists?
This has nothing to do with Ajax.
From the PHP manual:
Functions need not be defined before they are referenced, except when a function is conditionally defined
The order matters in your first example because the function is inside an if statement.
I think this issue is not related to calling file as Ajax request. This is more related to PHP's function declaration scope.
Consider the following situation:
if(true)
{
function bar()
{
}
$functions = get_defined_functions();
print_r($functions["user"]);
}
function foo()
{
}
this code will give bar and foo as defined functions.
But the following situation produces just foo function:
if(true)
{
$functions = get_defined_functions();
print_r($functions["user"]);
function bar()
{
}
}
function foo()
{
}
From this we see that all the function in a file are defined and available imediately when the file is loaded, but if blocks are interpreted as the execution passes step by step.
Hope this helps.
1 function foo($i){
2 return bar($i)*4;
3 function bar($i){
4 return $i*4;
5 }
6 }
7 echo foo(4);
return
Fatal error: Call to undefined function bar() in /var/www/index.php on line 2
why doesn't it work? it works well in javascript, while it works when i do this:
function foo($i){
return bar($i)*4;
}
function bar($i){
return $i*4;
}
Define the function above your return value, otherwise it never gets executed.
<?php
function foo($i){
function bar($i){
return $i*4;
}
return bar($i)*4;
}
echo foo(4);
?>
It doesn't work as you are calling bar() before it has been created.
See example 2 here:- http://www.php.net/manual/en/functions.user-defined.php
Your code never reach function bar(...), therefore it's never defined.
You need to put your bar() function before your foo() or before the return bar. (Answer based on your first example).
With your second example you probably define bar() before you use foo() therefore bar() is defined and it works fine.
So as long as you have your function defined when you hit a certain spot in your code it works fine, no matter if it's called from within another function.
If you define function within another function, it can be accessed directly, but after calling parent function.
For example:
function a () {
function b() {
echo "I am b.";
}
echo "I am a.<br/>";
}
//b(); Fatal error: Call to undefined function b() in E:\..\func.php on line 8
a(); // Print I am a.
b(); // Print I am b.
Execution not execute after return statement
change your code like this
function foo($i){
function bar($i){
return $i*4;
}
return bar($i)*4;
}
echo foo(4);
For the sake of having a "recent" answer, here's what I did:
function printRx($conn, $patient)
{
function rows($rows, $tod)
{
for ($x = 0; $x < count($tod); $x++) {
if ($tod[$x] == 1) {
$rows++;
break;
}
}
return $rows;
}
$tod['prn'] = (explode('|', $row['prn'])) ?? null;
$rows = rows($rows, $tod['prn']);
return;
}
Works beautifully