3

I saw a strange behaviour in PHP. See this example:

<?php
if (true)
    function my_function(){
        echo "here";
    }

my_function();
?>

Running this will give an error:

Parse error: syntax error, unexpected 'my_function' (T_STRING), expecting '(' on line 4

I found that the fix to this error is to add parenthesis:

<?php
if (true) {
    function my_function(){
        echo "here";
    }
}
my_function();
?>

This code will run properly.

Can you explain it? Why defining a function count as more than one statement?

Dharman
  • 30,962
  • 25
  • 85
  • 135
zvi
  • 3,677
  • 2
  • 30
  • 48
  • 2
    it's not - although you can omit the opening bracket, only if the condition block is a one-liner, or else it leads to weird parsing errors - a reason I hate to omit it to begin with. – treyBake Nov 19 '19 at 15:01
  • Sorry, by one-liner I mean, not declaring a new condition block - I mean pure execution (as in, something like `if ($foo) echo 'hi';`) – treyBake Nov 19 '19 at 15:11
  • [The manual on functions](https://www.php.net/manual/en/functions.user-defined.php) states: *"Functions need not be defined before they are referenced, **except** when a function is conditionally defined as shown in the two examples below. When a function is defined in a conditional manner such as the two examples shown. Its definition must be processed **prior** to being called."* – Funk Forty Niner Nov 19 '19 at 15:14
  • 3
    Except the function *is* being defined (albeit conditionally) before it's being called... logically there should be no difference between `if(true) function my_function() { echo "here"; }` and `if(true) { function my_function() { echo "here"; } }` ... but the first one throws a syntax error, the second works. – CD001 Nov 19 '19 at 15:19
  • 2
    They should (always) be using proper bracing then @CD001 which is probably the root of the error. – Funk Forty Niner Nov 19 '19 at 15:20
  • 1
    @FunkFortyNiner - I'm not debating that ;) ... hell, even the idea of a *conditional function* doesn't sit right with me ... but *logically* I think the OP has a point. `if($foo) echo "bar"` is fine but `if($foo) function bar() {}` isn't ... and I'm not sure *why*. Granted it's not something that I've ever attempted before but the behaviour seems ... unintuitive. – CD001 Nov 19 '19 at 15:24
  • Curiously it's perfectly happy with a self-executing closure: `if(true) (function() { $s = "here"; echo $s; })();` ... if you're happy with your PHP looking remarkably like JS (O_o) - you just can't *define* the function in a one-line conditional it seems. – CD001 Nov 19 '19 at 15:37

1 Answers1

1

Function definition is not a statement.

You asked:

Why defining a function count as more than one statement?

It doesn't. Defining a function is not a statement.

From PHP Manual:

A statement can be an assignment, a function call, a loop, a conditional statement or even a statement that does nothing (an empty statement). Statements usually end with a semicolon. In addition, statements can be grouped into a statement-group by encapsulating a group of statements with curly braces. A statement-group is a statement by itself as well.

An if statement must be followed by another statement! Let's simplify your problem and see what are some examples of such statements as defined above:

if(1)
    {} // A statement-group is a statement by itself as well.
if(1)
    ; // an empty statement
if(1)
    $a=1; // an assignment
if(1)
    print(1); // a function call
if(1)
    while(0){} // a loop
if(1)
    if(0); // a conditional statement

A definition of function or class is not a statement per the official PHP definition. A non-statement cannot be used in the context where a statement is expected.

When a function definition is a statement?

PHP 5.3 has introduced a concept of anonymous functions (Lambda Functions and Closures). An anonymous function definition is a statement.

The syntax of anonymous function is almost the same as the normal function definition, but you are expected to provide no name. In other words keyword function must be followed by () with only whitespace allowed between them. It must also end in semicolon.

// This is valid:
if(1)
    function (){};
//This is invalid:
if(1)
    function a(){}
//           ^
// syntax error, unexpected 'a' (T_STRING), expecting '('

This is why the error message is telling you that the name of the function is unexpected. PHP expects a statement and when it encounters function keyword, it expects that you are defining an anonymous function. An anonymous function doesn't have a name, so the name part is unexpected.

Community
  • 1
  • 1
Dharman
  • 30,962
  • 25
  • 85
  • 135