user1615069
user1615069

Reputation: 633

Get all public methods declared in the class, not inherited

What I want to get is the array of all public methods, and ONLY public ones, from the lowest classes in the inheritance tree. For example:

class MyClass {  }

class MyExtendedClass extends MyClass {  }

class SomeOtherClass extends MyClass {  }

And from the inside of MyClass I want to get all PUBLIC methods from MyExtendedClass and SomeOtherClass.

I figured out I can use Reflection Class to do this, however when I do that, I also get methods from the MyClass, and I don't want to get them:

$class = new ReflectionClass('MyClass');
$methods = $class->getMethods(ReflectionMethod::IS_PUBLIC);

Is there a way to do this? Or the only solution I have in this situation is just to filter out the outcomes of the Reflection Class?

Upvotes: 18

Views: 12025

Answers (4)

A. Khaled
A. Khaled

Reputation: 1608

You can compare getDeclaringClass against static::class. For example in base class you can declare one helper method like following

final public function events()
{
    return array_reduce(
        (new ReflectionClass($this))->getMethods(ReflectionMethod::IS_PUBLIC),
        function (array $carry, ReflectionMethod $method) {
            if ($method->getDeclaringClass()->name === static::class) {
                array_push($carry, $method->getName());
            }

            return $carry;
        },
        []
    );
}

Upvotes: 0

Daniel
Daniel

Reputation: 3806

No, I don't think you can filter out the parent methods at once. But it'd be quite simple to just filter the results by the class index.

$methods = [];
foreach ($reflection->getMethods(ReflectionMethod::IS_PUBLIC) as $method)
    if ($method['class'] == $reflection->getName())
         $methods[] = $method['name'];

Upvotes: 23

Jelmergu
Jelmergu

Reputation: 964

I had the need to do the same and came up with the following function:

function getMethods($class, $visibility = "")
{

    $reflect = new ReflectionClass($class);
    $methods = [];
    // Iterate the methods
    foreach ($reflect->getMethods() as $value){

        /*
         * $value->getFileName() returns actual file name a method was set in.
         * if it does not match the current filename it is a inherited method assuming a file contains only one class
         */
        if ($value->getFileName() == $reflect->getFileName()) {
            if ($value->isPublic() === true) {
                $methods['public'][] = $value->name;
            }
            elseif ($value->isPrivate() === true) {
                $methods['private'][] = $value->name;
            }
            elseif ($value->isProtected() === true) {
                $methods['protected'][] = $value->name;
            }
        }
    }
    switch ($visibility) {
        case "private":
        case "public":
        case "protected":
            return $methods[$visibility];
            break;
        default:
            return $methods;
            break;
    }
}

Using the following test code in Father.php and Child.php

class Father{
    public function parentTest() { }
}
class Child extends Father {
    public function __construct() { }
    private function test() { }
    protected function test2() { }
}

Which returns the following:

   array (size=3)
  'public' => 
    array (size=1)
      0 => string '__construct' (length=11)
  'private' => 
    array (size=1)
      0 => string 'test' (length=4)
  'protected' => 
    array (size=1)
      0 => string 'test2' (length=5)

Upvotes: 1

Dieter Gribnitz
Dieter Gribnitz

Reputation: 5208

I just wrote a method with some extra functionality that expands on Daniel's answer.

It allows you to return static or object methods only.

It also allows you to only return methods that have been defined in that class.

Supply your own namespace or just copy the method.

Example Usage:

$methods = Reflection::getClassMethods(__CLASS__);

Code:

<?php

namespace [Your]\[Namespace];

class Reflection {
    /**
     * Return class methods by scope
     * 
     * @param string $class
     * @param bool $inherit 
     * @static bool|null $static returns static methods | object methods | both
     * @param array $scope ['public', 'protected', 'private']
     * @return array
     */
    public static function getClassMethods($class, $inherit = false, $static = null, $scope = ['public', 'protected', 'private'])
    {
        $return = [
            'public' => [],
            'protected' => [],
            'private' => []
        ];
        $reflection = new \ReflectionClass($class);
        foreach ($scope as $key) {
            $pass = false;
            switch ($key) {
                case 'public': $pass = \ReflectionMethod::IS_PUBLIC;
                    break;
                case 'protected': $pass = \ReflectionMethod::IS_PROTECTED;
                    break;
                case 'private': $pass = \ReflectionMethod::IS_PRIVATE;
                    break;
            }
            if ($pass) {
                $methods = $reflection->getMethods($pass);
                foreach ($methods as $method) {
                    $isStatic = $method->isStatic();
                    if (!is_null($static) && $static && !$isStatic) {
                        continue;
                    } elseif (!is_null($static) && !$static && $isStatic) {
                        continue;
                    }
                    if (!$inherit && $method->class === $reflection->getName()) {
                        $return[$key][] = $method->name;
                    } elseif ($inherit) {
                        $return[$key][] = $method->name;
                    }
                }
            }
        }
        return $return;
    }
}

Upvotes: 4

Related Questions