Bug #51527 [Opn->Bgs]: is_callable() returning true for non-static callbacks

[email protected] Sat, 10 Apr 2010 17:55:25 +0200 (CEST)
Newsgroups php.bugs
Message-ID <[email protected]>
Edit report at http://bugs.php.net/bug.php?id=51527&edit=1

 ID:               51527
 Updated by:       [email protected]
 Reported by:      [email protected]
 Summary:          is_callable() returning true for non-static callbacks
-Status:           Open
+Status:           Bogus
 Type:             Bug
 Package:          Class/Object related
 Operating System: Linux
 PHP Version:      5.3.2

 New Comment:

The method can always be called statically. The access to $this might be
forbidden but the method itself can be called. is_callable() doesn't
mean it will execute properly. (the $this error is basically the same as
a call to an undefined funciton in there or such)

To change this the only way would be to forbid calling non-static
methods statically. Maybe this can be done nowadays (we needed the
behavior for PHP 4 compatibility) but that's no bug but requires a RFC
and discussion on internals as this might break quite a few applications
(many PEAR-based things, many legacy applications not fully "converted"
to PHP 5 ....)


Previous Comments:
------------------------------------------------------------------------
[2010-04-10 16:43:31] [email protected]

@pajoye: Yes, this particular example was callable. However, if the
method is 
actually an instance method, and has references to $this, is_callable()
still 
returns true -- making it an invalid test to use to determine whether or
not it's 
safe to then call call_user_func(). Instead, to really determine if the
callback 
is valid, you have to start doing a bunch of reflection -- checking to
see if the 
method is defined and static, or if there is a __callStatic defined that
would 
intercept the call.

That's the more serious implication of the behavior, and why it needs to
be 
fixed.

------------------------------------------------------------------------
[2010-04-10 16:29:12] [email protected]

It is actually callable. But calling it statically breaks the strict
standards, but the strict standards will break BC in many situations.

I would suggest to make this change in trunk only.

------------------------------------------------------------------------
[2010-04-10 16:07:17] [email protected]

Description:
------------
is_callable() is returning a false-positive for callbacks that reference
non-
static methods. As an example, if I have defined a class 'Foo' with an
instance 
(i.e., non-static) method 'bar', and define the callback "array('Foo',
'bar')", 
is_callable() will falsely return true.

Additionally, if you then pass this callback to call_user_func(), this
latter 
function will actually try to call the method statically -- and raise an

E_STRICT about the callback being invalid. If the method has any
references to 
$this, it then fails with an E_FATAL, but otherwise it will run the
method as if 
it were static.

This behavior is unexpected, and unintuitive. Calling non-static methods
as if 
they were static, even when they do not reference $this, violates
visibility. I 
would expect is_callable() to return false in these instances, and for 
call_user_func() to immediately raise an E_FATAL if the method is not
defined as 
static.

Test script:
---------------
class Foo
{
    public function bar()
    {
        return 'foo bar';
    }
}

$callback = array('Foo', 'bar');
if (is_callable($callback)) {
    echo call_user_func($callback);
}

Expected result:
----------------
No output.

Actual result:
--------------
PHP Strict Standards:  call_user_func() expects parameter 1 to be a
valid 
callback, non-static method Foo::bar() should not be called statically

Strict Standards: call_user_func() expects parameter 1 to be a valid
callback, 
non-static method Test\Foo::bar() should not be called statically
foo bar


------------------------------------------------------------------------



-- 
Edit this bug report at http://bugs.php.net/bug.php?id=51527&edit=1