获取在类中声明的所有公共方法,而不是继承

时间:2012-10-10 17:40:49

标签: php oop reflection

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

class MyClass {  }

class MyExtendedClass extends MyClass {  }

class SomeOtherClass extends MyClass {  }

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

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

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

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

3 个答案:

答案 0 :(得分:18)

不,我认为你不能一次过滤出父方法。但是通过类索引过滤结果非常简单。

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

答案 1 :(得分: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;
    }
}

答案 2 :(得分: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)