如何将PHP回调作为非字符串传递,从而使其成为可重构的?

Introduced in PHP 5.5, it is possible to use the MyClass::class syntax to reference a class instead of passing it as 'MyClass', which is not easily refactorable as it's just a string.

I would very much like to do the same thing with the function name, when passing a callback/callable to call_user_func() or usort().

In the example

usort($files, [FileFunctions::class, 'dircmp']);

only FileFunctions can easily be refactored.

How can I reference the dircmp function in a similar way?

Using

usort($a, FileFunctions::dircmp);

leads to a Undefined class constant 'dircmp' fatal error, as the parameter after the double colons is interpreted as a constant (of course).

<?php

class FileFunctions {
    static function dircmp($a, $b) {
        if ($a == $b) return 0;
        return ($a > $b) ? 1:-1;
    }
}

$files = [2,6,1,6,9,2,6,1,7,4];

usort($files, function($a, $b) {return FileFunctions::dircmp($a, $b);});
var_dump($files);

PHPStorm10 correctly refactored dircmp

There are some interesting dicussions regarding this in this reddit thread: https://www.reddit.com/r/PHP/comments/47jxd0/rfc_callable_constructors/d0eip6k

the current syntax for calling dynamically using methods as a callback is rather awful

That seems a difficult problem to solve. People who've looked at it have said that it can't be solved without either merging the symbol tables (which isn't ever likely to happen, as it breaks too much code), or alternatively with a new syntax. One thing that would be possible without clashing with any existing syntax is to use $() to be a language construct of 'give me a callable/closure' of this thing:

$(functionName);  // Usable at compile time.
$(SomeClass::staticMethodNameAsString); //Usable at compile time
$($object->methodName); //Usable at runtime

Without merging the symbol tables, that's almost certainly the cleanest, in the sense of the smallest number of characters, to implement it. I can't see any problems with that (other than it's new syntax which everyone gets scared by), but it's beyond my skills to implement.

and

Props for taking the feedback well. There's definitely need for the problem to be solved in a cleaner way than our current options.

I completely agree that solving the greater callback syntax is very tricky. Even some sort of syntactic sugar that converts a method call into the current array-as-callable could help a lot. The main issue I have with explicitly using strings is that it makes finding call sites of methods drastically harder, both with static analysis and even basic tools like grep. You can't simply grep -ri -- '->someMethodCall(' * when it's being invoked with [$obj, 'someMethodCall'], and looking for the method name without arrows or parens tends to leave a lot of false positives.