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

2

4

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.

Incommunicado answered 27/2, 2012 at 20:34 Comment(6)
What is that you are trying to achieve?Semiconductor
I want to know if a method was inherited from a parent class or defined in the class being "reflected" (i.e. not inherited). What is that you don't understand precisely?Incommunicado
@Matthieu: You must want to do that for a reason - what is that reason (your end goal)? I'm not too familiar with the Reflection API, but are you even able to access methods that are only defined in the parent class?Constructive
@Madmartigan Yes I end up with methods of the class and methods of the parent class (and I want to keep only the methods of the current class)Incommunicado
@Matthieu: No offense, but some people on this site ask questions based on ideas that are already pointed in the wrong direction. You didn't explain your use case, so it's difficult to tell if using the Reflection class is actually the correct tool to achieve your goals. If your only goal is as stated, then I don't see the point. There must be something beyond that which you are trying to accomplish.Constructive
@Madmartigan Yes, I know exactly what you mean. I get those comments all the time because I often ask weird questions and people think I'm doing it wrong (because many questions are like that in here)... I'm trying to make an AOP framework for PHP, I'm using Reflection in the process.Incommunicado
C
5

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";
}
Comehither answered 27/2, 2012 at 20:46 Comment(3)
OK I see what you're doing, but in the case of abc, I will know that's in the parent class, but I won't know if it's defined in Bar (there is no difference between inherited or overrided). I want to keep only the methods of Foo.Incommunicado
I updated the example to show how to check if the method is in Bar. You should be able to use a combination of the if statements to get the result you are looking for.Comehither
You can also use ReflectionMethod::getPrototype() instead. This method is a bit more straightforward.Salomo
S
5

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
)
Salomo answered 27/2, 2012 at 21:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.