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

 ID:               51527
 Updated by:       paj...@php.net
 Reported by:      weierophin...@php.net
 Summary:          is_callable() returning true for non-static callbacks
-Status:           Bogus
+Status:           Open
 Type:             Bug
 Package:          Class/Object related
 Operating System: Linux
 PHP Version:      5.3.2

 New Comment:

I don't like the optional flag idea. You can disable strictness using
error_reporting already.



However I would like to see this change in trunk, can you come up with a
RFC pls?


Previous Comments:
------------------------------------------------------------------------
[2010-04-10 20:19:45] weierophin...@php.net

@johannes Perhaps an optional "strict" flag to is_callable() would
address this? 

That would keep BC, while allowing for better checking for >= PHP-5
apps. Usage 

would be:



$callback = array('Foo', 'bar');



if (is_callable($callback, true)) {

    // Passed strict check

} else {

    // failed strict check

}



Thoughts?

------------------------------------------------------------------------
[2010-04-10 17:55:25] johan...@php.net

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 ....)

------------------------------------------------------------------------
[2010-04-10 16:43:31] weierophin...@php.net

@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] paj...@php.net

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] weierophin...@php.net

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

Reply via email to