2010-09-14 4 views
6

Здравствуйте, мне нужно получить только методы, объявленные в классе, а не унаследованные методы. Мне нужно это для cakePHP. Я получаю все контроллеры, загружая их и получая методы от этих контроллеров. Но не только объявленные методы приходят, но и унаследованные.Получить только объявленные методы класса в PHP

Есть ли способ получить только объявленные методы.

+0

Я не знаю метода, кроме сложного отражения. Для чего вам это нужно? –

+0

Можете ли вы сообщить мне, почему вы это делаете? Это для документации или для использования в приложении? –

+0

Мне нужно добавить все общедоступные методы в контроллерах в мою таблицу разрешений. Я использую cakePHP, и их компонент ACL не работает с существующей моделью, которую у меня есть. – macha

ответ

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

+0

Чтобы ограничить его общедоступными только методами. Если вы хотите все методы, просто опустите это ... – ircmaxell

+0

Следует упомянуть, так как он делает ответ неполным на вопрос. – chelmertz

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

?> 

Вы получите список методов, определенных B и A, вместе с классом, что последний определил его. Это выход:

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

+2

Хм, я думаю, это личное предпочтение. Для меня отражение похоже на исправление исполняемых файлов в памяти и * может * быть неожиданным (или выставлять такое поведение), если оно не документировано и может сделать ваш код более запутанным или ввести побочные эффекты. Однако это может оказаться полезным для написания фреймворков и метапрограмм/расширения возможностей языка. – Archimedix

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; 
} 
Смежные вопросы