0

Since PHP7 it seems to be possible to directly call anonymous functions like this:

(function () { echo 'Hello!'; })();

I found this by accident in some open source code base. I tried to find any hint on this in the PHP documentation (including changelogs and RFCs). There seems to be none, it seems fully undocumented.

Is it safe to call functions this way or should I use call_user_func(); like in the old days? Is this documented somewhere?

I know of these questions and answers:

They just say it's supposed to work and how it works. I know this. My question is not about the "how"! It's about whether this is actually an official PHP feature or if it'S merely working "by accident" (because it seems undocumented).

Foo Bar
  • 1,764
  • 4
  • 24
  • 43
  • 1
    Does this answer your question? [IIFE (Immediately Invoked Function Expression) in PHP?](https://stackoverflow.com/questions/35044452/iife-immediately-invoked-function-expression-in-php) – Thomas Sablik Feb 02 '21 at 21:48
  • @ThomasSablik No, it just states this as a (supposed) fact (I saw this question already). No links to any official documentation. I don't like to rely on undocumented features. – Foo Bar Feb 02 '21 at 21:49
  • Please don't vote for closing so fast... I'm asking whether this is safe and documented, not how to use it (I know how to use it). – Foo Bar Feb 02 '21 at 21:52
  • 1
    I'm not sure if it is explicitly documented in any programming standard but many languages support it. That's not a special case. It's part of the language syntax. If you ask this question please make clear why it shouldn't work. – Thomas Sablik Feb 02 '21 at 21:56
  • It was not working in PHP5 and it's working in PHP7. But this change seems not documented. So to me it looks like I can not rely on this feature. Or can I? This is the question. :) – Foo Bar Feb 02 '21 at 21:57
  • 1
    How would you define "safe"? Why should using this not be "safe"? – Nico Haase Feb 02 '21 at 21:58
  • If this syntax is not documented (because it'S workign by accident) it can change with any minor PHP release.... Is this so hard to understand? That I require a language to be formally defined? All I'm askign is if this is documented or not... – Foo Bar Feb 02 '21 at 21:59
  • 2
    yes, it's [documented](https://wiki.php.net/rfc/uniform_variable_syntax) - _Newly added and generalized syntax_ – berend Feb 02 '21 at 22:19
  • If you want to ensure that your code works after upgrading PHP, just write a test covering this use case ;) – Nico Haase Feb 02 '21 at 22:23

2 Answers2

5

The reason you won't find this documented as a feature in the main manual is because it isn't one, it's just a consequence of other features:

  • function () { echo 'Hello!'; } creates a Closure object
  • putting () after a Closure object executes that closure

That's not quite the same as accidental, but I can see why you might think that, because it didn't work in PHP 5.

The reason it changed is that PHP's parser was overhauled in PHP 7.0 to use more consistent rules when parsing variables, as well as introducing an extra stage called an Abstract Syntax Tree. This changed the meaning of some code, but allowed for other cases that logically should have been possible, but were previously hard to implement.

Allowing code that was previously a syntax error is not generally considered a compatibility break, so not every piece of syntax enabled by this change made it into migration guides.

However, removing this functionality - even if not documented - would be a compatibility break, so at the very least you will get some notice that it's going to change, and it would be in a "major version" (9.0, 10.0, etc). Since it's a useful piece of syntax, there's no reason to suppose it will ever stop working, unless there's some even more useful feature that conflicts with it for some reason.

IMSoP
  • 89,526
  • 13
  • 117
  • 169
2

Just to put some thoughts together: (function () { echo 'Hello!'; }) defines a class instance of type Closure. Putting the closure into a variable helps to understand that:

$x = (function () { echo 'Hello!'; });
echo gettype($x);

This prints object, since PHP 5.3. The result of $x(); hasn't changed since PHP 5.3 either. But what has changed is the unified handling of variables - this enables that you don't have to define a variable explicitly, but call the closure directly as if you had put it in a variable first

Nico Haase
  • 11,420
  • 35
  • 43
  • 69