php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #68475 call_user_func($a) not equivalent to $a()
Submitted: 2014-11-21 19:48 UTC Modified: 2015-05-12 11:45 UTC
Votes:2
Avg. Score:4.0 ± 1.0
Reproduced:1 of 2 (50.0%)
Same Version:1 (100.0%)
Same OS:0 (0.0%)
From: nicolas dot grekas+php at gmail dot com Assigned: jpauli
Status: Closed Package: Scripting Engine problem
PHP Version: 5.6.3 OS:
Private report: No CVE-ID:
 [2014-11-21 19:48 UTC] nicolas dot grekas+php at gmail dot com
Description:
------------
Since php5.4, call_user_func($a) is almost equivalent to $a()
$a() works with all callables BUT ONE.
A "foo::bar" string is OK for call_user_func(), but KO for pure syntax.
This make the new (and more performant) syntax useless in generic code that want to accept any callable.

Test script:
---------------
<?php

class foo{static function bar(){}}

$a = 'foo::bar';
echo is_callable($a),"\n";
call_user_func($a);
$a();


Expected result:
----------------
1

Actual result:
--------------
1
Fatal error: Call to undefined function foo::bar() in ... on line 7

Patches

Add a Patch

Pull Requests

Pull requests:

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-11-29 11:02 UTC] jpauli@php.net
-Assigned To: +Assigned To: jpauli
 [2014-12-01 03:39 UTC] laruence@php.net
for the record, they are never guaranteed to be act the same.

and, there is voice to deprecated call_user_** at all.

so I don't think the fix is worthy to do (slowdown the fast path) ..

thanks
 [2014-12-01 03:39 UTC] laruence@php.net
for the record, they are never guaranteed to be act the same.

and, there is voice to deprecated call_user_** at all.

so I don't think the fix is worthy to do (slowdown the fast path) ..

thanks
 [2014-12-01 07:10 UTC] nicolas dot grekas+php at gmail dot com
This check for double double colons is implemented for the callable type hint.
This means that the performance argument is not relevant (since a type hint is checked as often if not more often than a callable is effectivelly called).

More importantly, it means that the type hint is useless in the general case, since it gives no guarantee whatsoever when the `$callable()` syntax is used instead of the `call_user_func($callable)` one.

Last but not least, making `$callable()` not an equivalent for `call_user_func($callable)` just because of this case is a blocker for deprecating the former, since there will always be a valid use case for it. 
Especially since most of the code out there uses `call_user_func($callable)`, because of history.
 [2014-12-01 11:18 UTC] dmitry@php.net
This behavior was never supported in PHP5, so it's not a bug but a feature request. I think, such change may be accepted in PHP7 (no way for php-5.6).
The real "fast" path (when OP2_TYPE == IS_CONST) must not be affected.
The implementation is not a problem (I can take care about it), but such change should be approved. I'm not sure if this needs RFC or not (probably better to follow the standard RFC procedure).
 [2014-12-04 11:03 UTC] stof at notk dot org
> This behavior was never supported in PHP5, so it's not a bug but a feature request. I think, such change may be accepted in PHP7 (no way for php-5.6).

Well, "foo::bar" callables are supported by PHP in all places except the $a() syntax:

- is_callable is returning true for them
- the callable typehint accepts them
- call_user_func and call_user_func_array accept them.

So this means that callables in PHP still cannot be called directly. PHP 5.4 only expanded the support for direct call, but it is still incomplete.

So this makes it a blocker for deprecating the call_user_func functions altogether, as they are still the only reliable way to call a generic callable.
 [2014-12-04 19:37 UTC] nikic@php.net
I don't get why this is a blocker for anything. Why not just use the standard ['Class', 'method'] callback style?

Imho the 'Class::method' style is just unnecessary duplication and should be removed in the future, rather than implemented in more places.
 [2014-12-14 15:19 UTC] nicolas dot grekas+php at gmail dot com
You can't say "just use the standard ['Class', 'method'] callback style"; there are of code out there that use the 'Class::method' style, you can't ignore it. This is where the blocker is: BC
 [2014-12-16 13:19 UTC] jpauli@php.net
I agree that for consistency, this should be supported
 [2015-01-08 20:16 UTC] aharvey@php.net
-Type: Bug +Type: Feature/Change Request
 [2015-01-08 20:16 UTC] aharvey@php.net
I might prefer unifying the VM code with the code call_user_func() and friends use: something like https://github.com/LawnGnome/php-src/compare/call-static-methods?expand=1 (albeit I think we'd want to refactor the critical code path out of zend_is_callable_check_func() into a separate function to minimise the overhead). Having two sources of truth for what a string callable can look like is what got us in this mess. :)

Whatever the approach, let's do this in PHP 7. Julien, do you want to write the RFC, or shall I?
 [2015-01-09 11:47 UTC] jpauli@php.net
I don't think we need to RFC that.
What we want, is uniformisation and consistency in the way we can call a PHP function from a PHP string.
No new idea, no debatte, no RFC needed.
 [2015-05-07 08:44 UTC] me at evertpot dot com
Personally I think the major issue here is not so much that if call_user_func($a) is not equivalent to $a(), but rather that both is_callable and the callable typehint accepts a value that can't be invoked with $x().
 [2015-05-12 11:45 UTC] jpauli@php.net
-Status: Assigned +Status: Closed
 [2015-05-12 11:45 UTC] jpauli@php.net
Please try using this snapshot:

  http://snaps.php.net/php-trunk-latest.tar.gz
 
For Windows:

  http://windows.php.net/snapshots/

This is fixed in PHP7
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Tue Aug 29 15:01:52 2017 UTC