【问题标题】:Get only declared methods of a class in PHP仅获取 PHP 中类的声明方法
【发布时间】:2010-09-14 20:32:39
【问题描述】:

您好,我只需要获取类中声明的方法,而不需要继承的方法。我需要这个用于 cakePHP。我正在获取所有控制器,加载它们并从这些控制器中检索方法。但是不仅声明的方法来了,继承的方法也来了。

是否有任何方法可以仅获取已声明的方法。

【问题讨论】:

  • 除了复杂的反射之外,我不知道任何方法。你需要这个做什么?
  • 你能告诉我你为什么这样做吗?它是用于文档还是在应用程序中使用?
  • 我需要将控制器中的所有公共方法添加到我的权限表中。我正在使用 cakePHP,它们的 ACL 组件不适用于我现有的模型。
  • @Joe- 我需要将所有方法添加到数据库中的表中。我正在使用 cakePHP,他们的 ACL 组件不适合我现有的模型。
  • 你可以编辑你知道的cmets :)

标签: php oop cakephp


【解决方案1】:

您可以使用ReflectionClass 来做到这一点(虽然比“简单”多一点)

function getDeclaredMethods($className) {
    $reflector = new ReflectionClass($className);
    $methodNames = array();
    $lowerClassName = strtolower($className);
    foreach ($reflector->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
        if (strtolower($method->class) == $lowerClassName) {
            $methodNames[] = $method->name;
        }
    }
    return $methodNames;
}

【讨论】:

  • 你为什么使用ReflectionMethod::IS_PUBLIC
  • 应该提一下,因为它使问题的答案不完整。
【解决方案2】:

从架构的角度来看,我认为应尽可能避免反射,但如果您认为自己知道自己在做什么,请查看ReflectionClass->getMethods()

<?php

class A {
    public function x() { }
    public function y() { }
}

class B extends A {
    public function a() { }
    public function b() { }
    public function x() { } // <-- defined here
}

$r = new ReflectionClass('B');
print_r($r->getMethods());

?>

您将获得由BA 定义的方法列表,以及最后定义它的类。这是输出:

Array
(
    [0] => ReflectionMethod Object
        (
            [name] => a
            [class] => B
        )

    [1] => ReflectionMethod Object
        (
            [name] => b
            [class] => B
        )

    [2] => ReflectionMethod Object
        (
            [name] => x
            [class] => B
        )

    [3] => ReflectionMethod Object
        (
            [name] => y
            [class] => A
        )

)

【讨论】:

  • “从架构的角度来看,我认为应该尽可能避免反射”为什么会这样?
  • 嗯,我想这是个人喜好。对我来说,反射类似于在内存中修补可执行文件,并且可能是出乎意料的(或暴露此类行为),除非有充分的文档记录,并且会使您的代码更加复杂或引入副作用。但是,它可能对编写框架和元编程/扩展语言功能很有用。
【解决方案3】:

看到一条评论:“ReflectionClass::getMethods() 按类对方法进行排序(在继承树中首先是最低的),然后按照它们在类定义中定义的顺序排序”这里 - http://php.net/manual/en/reflectionclass.getmethods.php#115197

我验证了这一点,这似乎是真的。基于这个事实,我们可以对 ircmaxell 的解决方案进行一些优化,以避免迭代其他继承的方法。还添加了一些清理以避免构造函数\析构函数:

public function getMethods($className) 
{   
    $methodNames = [];
    $reflectionClass = new ReflectionClass(className); 
    $publicMethods = $reflectionClass->getMethods(ReflectionMethod::IS_PUBLIC);
    $lowerClassName = strtolower($className);
    foreach ($publicMethods as $method) {
        if (strtolower($method->class) == $lowerClassName) {
            // You can skip this check if you need constructor\destructor  
            if (!($method->isConstructor() ||
                $method->isDestructor())) {
                $methodNames[] = $method->getName();
            }
        } else {
            // exit loop if class mismatch
            break;
        }
    }
    return $methodNames;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-28
    • 1970-01-01
    相关资源
    最近更新 更多