I am testing a project for PHP8.2 and have several places I have a subclass method overrides the parent method and passes the parent method to another class returning those results. Prior to 8.2, this looked something like:
$callable = [ $this, 'parent::myMethod' ];
return $anotherObject->call_callable_if_needed( $callable );
That relative callable is deprecated in PHP8.2 resulting in an warning "… PHP Deprecated: Callables of the form [“S2MySubClass“, "S2Base::myMethod"] are deprecated in …".
Reading the related PHP RFC (https://wiki.php.net/rfc/deprecate_partially_supported_callables) at the end it list using reflection and closure rebinding as an alternative to facilitate calling an overriden method outside inheritance. From that suggestion I created a callable using the ReflectionMethod class:
$callable = ( new ReflectionMethod( parent::class, 'myMethod' ) )->getClosure( $this );
Am I over-complicating this by using the ReflectionMethod? is there a simpler form of creating a supported callable for a parent method to pass to another class method?
A test code sample is below:
<?php
class TestParent {
public function myMethod(): string
{
return __METHOD__ . '() called';
}
}
class Test extends TestParent {
public function myMethod(): string
{
// PHP <= 8.1
// $callable = [ $this, 'parent::myMethod' ];
// PHP 8.2
$callable = ( new ReflectionMethod( parent::class, 'myMethod' ) )->getClosure( $this );
return TestExternal::anotherMethod( $callable );
}
}
class TestExternal {
public static function anotherMethod( callable $callable ): string
{
$result = call_user_func( $callable );
return $result . ' via ' . __METHOD__ . '()';
}
}
$test = new Test();
echo $test->myMethod();
Runnng that results:
% php test.php
TestParent::myMethod() called via TestExternal::anotherMethod()
2
Answers
One slightly simpler way to create a callable for the parent method without using reflection is to create a closure directly within the subclass:
as of PHP8.1, use the first-class callable syntax
3v4l: https://3v4l.org/L6L40#v8.2.10