skip to Main Content

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


  1. One slightly simpler way to create a callable for the parent method without using reflection is to create a closure directly within the subclass:

    class Test extends TestParent {
        public function myMethod(): string {
            // Create a closure that calls the parent method.
            $callable = function() {
                return parent::myMethod();
            };
    
            // Use the closure as the callable.
            return TestExternal::anotherMethod($callable);
        }
    }
    
    Login or Signup to reply.
  2. as of PHP8.1, use the first-class callable syntax

        $callable = parent::myMethod(...);
    

    3v4l: https://3v4l.org/L6L40#v8.2.10

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search