Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP Reflection: How to know if a ReflectionMethod is inherited?

In the ReflectionMethod documentation, I can't find anything to know wether a method was inherited from its parent class or defined in the reflected class.

Edit: I use ReflectionClass::getMethods(). I want to know for each method if it has been defined in the class being reflected, or if it has been defined in a parent class. In the end, I want to keep only the methods defined in the current class.

class Foo {
    function a() {}
    function b() {}
}

class Bar extends Foo {
    function a() {}
    function c() {}
}

I want to keep a and c.

like image 855
Matthieu Napoli Avatar asked Dec 27 '22 05:12

Matthieu Napoli


2 Answers

You should be able to call ReflectionMethod::getDeclaringClass() to get the class declaring the method. Then a call to ReflectionClass::getParentClass() to get the parent class. Lastly a call to ReflectionClass::hasMethod() will tell you if the method was declared in the parent class.

Example:

<?php
class Foo {
    function abc() {}
}

class Bar extends Foo {
    function abc() {}
    function def() {}
}


$bar = new Bar();

$meth = new ReflectionMethod($bar, "abc");
$cls = $meth->getDeclaringClass();
$prnt = $cls->getParentClass();

if ($cls->hasMethod($meth->name)) {
    echo "Method {$meth->name} in Bar\n";
}
if ($prnt->hasMethod($meth->name)) {
    echo "Method {$meth->name} in Foo\n";
}

$meth = new ReflectionMethod($bar, "def");
$cls = $meth->getDeclaringClass();
$prnt = $cls->getParentClass();

if ($cls->hasMethod($meth->name)) {
    echo "Method {$meth->name} in Bar\n";
}
if ($prnt->hasMethod($meth->name)) {
    echo "Method {$meth->name} in Foo\n";
}
like image 151
MitMaro Avatar answered Jan 11 '23 03:01

MitMaro


You can get the ReflectionMethod object for the method you are interested in, and then use getPrototype() to get the ReflectionMethod of the method in the parent class. If the method does not override a method in the parent, this will throw a ReflectionClass exception.

The following example code will create an array with method name as key and the class which defined the implementation in use for the reflected class.

class Base {
    function basemethod() {}
    function overridein2() {}
    function overridein3() {}
}
class Base2 extends Base {
    function overridein2() {}
    function in2only() {}
    function in2overridein3 () {}
}
class Base3 extends Base2 {
    function overridein3() {}
    function in2overridein3 () {}
    function in3only() {}
}

$rc = new ReflectionClass('Base3');
$methods = array();
foreach ($rc->getMethods() as $m) {
    try {
        if ($m->getPrototype()) {
            $methods[$m->name] = $m->getPrototype()->class;
        }
    } catch (ReflectionException $e) {
        $methods[$m->name] = $m->class;
    }
}

print_r($methods);

This will print:

Array
(
    [overridein3] => Base
    [in2overridein3] => Base2
    [in3only] => Base3
    [overridein2] => Base
    [in2only] => Base2
    [basemethod] => Base
)
like image 26
Francis Avila Avatar answered Jan 11 '23 03:01

Francis Avila