2010-09-14 27 views
6

您好,我只需要獲取在類中聲明的方法,而不是繼承的方法。我需要這個CakePHP。我得到所有的控制器,加載它們並從這些控制器中檢索方法。但是,不僅宣稱的方法即將到來,而且還有繼承的方法。獲取PHP中只有聲明的類的方法

是否有任何方法只獲取聲明的方法。

+0

我知道沒有方法,除了複雜的反射的東西。你需要做什麼? – 2010-09-14 20:36:12

+0

你能告訴我你爲什麼這麼做嗎?是爲了文檔還是在應用程序中使用? – 2010-09-14 20:37:12

+0

我需要將所有控制器中的公共方法添加到我的權限表中。我正在使用cakePHP,他們的ACL組件不能與我擁有的現有模型一起工作。 – macha 2010-09-14 20:39:02

回答

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; 
} 
+0

你爲什麼使用'ReflectionMethod :: IS_PUBLIC'? – chelmertz 2010-09-14 21:00:11

+0

將其限制爲公開唯一的方法。如果你想要所有的方法,只是省略了... – ircmaxell 2010-09-14 21:01:23

+0

但應該提到,因爲它使問題的答案不完整。 – chelmertz 2010-09-14 21:04:28

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 
     ) 

) 
+0

「從架構的角度來看,我認爲如果可能的話應該避免反思」爲什麼? – chelmertz 2010-09-14 20:49:08

+2

嗯,我想這是個人喜好。對我而言,反射與修補內存中的可執行文件類似,*可能會意外(或暴露此類行爲),除非有詳細記錄,並且可能會使代碼更復雜或引入副作用。但是,它可能對編寫框架和元編程/擴展語言功能非常有用。 – Archimedix 2010-09-14 21:14:55

0

遇到了一個評論:「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; 
}