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

问题描述 投票:0回答:4

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

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

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

php oop reflection
4个回答
23
投票

不,我不认为你可以一次性过滤掉父方法。但只需按类索引过滤结果就非常简单了。

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

4
投票

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

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

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

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

用法示例:

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

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)

0
投票

您可以将

getDeclaringClass
static::class
进行比较。例如,在基类中,您可以声明一个辅助方法,如下所示

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;
        },
        []
    );
}
© www.soinside.com 2019 - 2024. All rights reserved.