我想要得到的是继承树中最低类的所有公共方法的数组,并且只有公共方法。例如:
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);
有办法做到这一点吗?或者在这种情况下我唯一的解决方案就是过滤掉反射类的结果?
不,我不认为你可以一次性过滤掉父方法。但只需按类索引过滤结果就非常简单了。
$methods = [];
foreach ($reflection->getMethods(ReflectionMethod::IS_PUBLIC) as $method)
if ($method['class'] == $reflection->getName())
$methods[] = $method['name'];
我刚刚编写了一个具有一些额外功能的方法,该方法扩展了丹尼尔的答案。
它允许您仅返回静态或对象方法。
它还允许您仅返回该类中定义的方法。
提供您自己的命名空间或仅复制方法。
用法示例:
$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;
}
}
我需要做同样的事情并想出了以下功能:
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)
您可以将
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;
},
[]
);
}