php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #74998 callable typehint generates redundant and unnecessary deprecation warning
Submitted: 2017-07-27 21:07 UTC Modified: 2017-07-27 21:16 UTC
From: alex dot howansky at gmail dot com Assigned:
Status: Not a bug Package: Scripting Engine problem
PHP Version: 7.1.7 OS: Fedora 25
Private report: No CVE-ID: None
 [2017-07-27 21:07 UTC] alex dot howansky at gmail dot com
Description:
------------
If you have a function/method that takes an argument typehinted with callable, and you pass it an array of static strings which references a method that's not defined as static, you'll get a deprecation warning about making a static call to a non-static method -- even if you never actually invoke the callable. If you then invoke the callable, you'll get an identical second deprecation warning.

Note the test script. As is, it generates two identical warnings, on adjacent lines, one for the callable typehint, and one for the actual call. The first is unwanted and unnecessary. The warning should be triggered only when I actually make the deprecated call. Simply passing a static callable should not trigger the warning. I.e., PHP shouldn't warn me about something I might possibly do in the future, it should warn me only about things I've actually done.

Since the invocation will always generate a warning, there's no need to also generate one when validating the typehint. Otherwise, you will always get two identical warnings for a single issue.

Suppose I add some conditional logic to this method, to detect if the callable is static and automatically instantiate an object for it if so:

if (is_string($callable[0])) {
    call_user_func([new $callable[0], $callable[1]]);
} else {
    call_user_func($callable);
}

This should not generate any deprecation warnings, as nothing would ever get called statically. As it stands, in order to get rid of the warnings, I would have to remove the callable typehint.


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

error_reporting(E_ALL);

class Caller {
    public function call(callable $callable) {
        call_user_func($callable);
    }
}

class Foo {
    public function bar() {
        echo "here\n";
    }
}

$caller = new Caller();
$callable = ['Foo', 'bar'];
$caller->call($callable);

Expected result:
----------------
PHP Deprecated:  Non-static method Foo::bar() should not be called statically in /tmp/foo.php on line 7
here

Actual result:
--------------
PHP Deprecated:  Non-static method Foo::bar() should not be called statically in /tmp/foo.php on line 6
PHP Deprecated:  Non-static method Foo::bar() should not be called statically in /tmp/foo.php on line 7
here

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2017-07-27 21:15 UTC] nikic@php.net
-Status: Open +Status: Wont fix
 [2017-07-27 21:15 UTC] nikic@php.net
Both deprecation warnings are correct. And yes, you should absolutely drop the callable type hint, because what you are accepting is clearly not a callable.

It may help to consider what is going to happen when the deprecation is realized: Your code will already error at the typehint, not just at the call. Not generating a deprecation notice at the typehint would be disingenuous, as the typehint is going to throw exception in a future version of PHP.
 [2017-07-27 21:16 UTC] nikic@php.net
-Status: Wont fix +Status: Not a bug
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Apr 25 00:01:41 2024 UTC