在PHP中只获取类的声明方法

时间:2010-09-14 20:32:39

标签: php oop cakephp

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

是否有任何方法只能获取声明的方法。

3 个答案:

答案 0 :(得分:9)

您可以使用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;
}

答案 1 :(得分:1)

从架构的角度来看,我认为应尽可能避免反思,但如果您认为自己知道自己在做什么,请查看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
        )

)

答案 2 :(得分:0)

遇到一条评论:&#34; ReflectionClass :: getMethods()按类(首先在继承树中最低)对方法进行排序,然后按类定义&#34;中的顺序排序。在这里 - 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;
}