16

我想要得到的是继承树中最低类的所有公共方法的数组,而且只有公共方法。例如:

class MyClass {  }

class MyExtendedClass extends MyClass {  }

class SomeOtherClass extends MyClass {  }

从 MyClass 内部,我想从 MyExtendedClass 和 SomeOtherClass 中获取所有 PUBLIC 方法。

我发现我可以使用反射类来做到这一点,但是当我这样做时,我也从 MyClass 中获取方法,我不想得到它们:

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

有没有办法做到这一点?或者我在这种情况下唯一的解决方案就是过滤掉反射类的结果?

4

3 回答 3

20

不,我认为您不能一次过滤掉父方法。但是仅按类索引过滤结果会非常简单。

$methods = [];
foreach ($reflection->getMethods(ReflectionMethod::IS_PUBLIC) as $method)
    if ($method['class'] == $reflection->getName())
         $methods[] = $method['name'];
于 2012-10-10T17:48:14.137 回答
2

我刚刚编写了一个具有一些额外功能的方法,该方法扩展了 Daniel 的答案。

它只允许您返回静态或对象方法。

它还允许您仅返回已在该类中定义的方法。

提供您自己的命名空间或仅复制该方法。

示例用法:

$methods = Reflection::getClassMethods(__CLASS__);

代码:

<?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;
    }
}
于 2015-01-07T10:57:39.803 回答
1

我需要做同样的事情并想出了以下功能:

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;
    }
}

在 Father.php 和 Child.php 中使用以下测试代码

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

它返回以下内容:

   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)
于 2017-03-24T13:31:46.780 回答