Подтвердить что ты не робот

Получить все общедоступные методы, объявленные в классе, а не унаследованные

Я хочу получить массив всех общедоступных методов и ТОЛЬКО публичных из низших классов дерева наследования. Например:

class MyClass {  }

class MyExtendedClass extends MyClass {  }

class SomeOtherClass extends MyClass {  }

И изнутри MyClass я хочу получить все PUBLIC-методы из MyExtendedClass и SomeOtherClass.

Я понял, что могу использовать Reflection Class для этого, но когда я это делаю, я также получаю методы из MyClass, и я не хочу их получать:

$class = new ReflectionClass('MyClass');
$methods = $class->getMethods(ReflectionMethod::IS_PUBLIC);

Есть ли способ сделать это? Или единственное решение, которое у меня есть в этой ситуации, - это просто отфильтровать результаты класса Reflection?

4b9b3361

Ответ 1

Нет, я не думаю, что вы можете сразу отфильтровать родительские методы. Но было бы просто просто отфильтровать результаты по индексу класса.

$methods = [];
foreach ($reflection->getMethods(ReflectionMethod::IS_PUBLIC) as $method)
    if ($method->class == $reflection->getName())
         $methods[] = $method->getName();

Ответ 2

Я просто написал метод с некоторыми дополнительными функциями, которые расширяются при ответе Даниэля.

Он позволяет вам возвращать только статические или объектные методы.

Он также позволяет вам возвращать только те методы, которые были определены в этом классе.

Поставьте свое собственное пространство имен или просто скопируйте метод.

Пример использования:

$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;
    }
}

Ответ 3

Мне нужно было сделать то же самое и придумал следующую функцию:

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)