Я создаю API, где пользователь запрашивает «команду», которая передается в класс. Предполагая, что команда соответствует функции PUBLIC, она будет выполнена успешно. Если команда соответствует функции ЗАЩИЩАЕТСЯ, она должна выдать ошибку.
Идея состоит в том, что функции можно отключить, изменив их с PUBLIC на PROTECTED, вместо того, чтобы переименовывать их или удалять.
В настоящее время я делаю это, но неважно, является ли команда открытой или защищенной.
<?php /** * Look for Command method */ $sMethod = "{$sCommand}Command"; if (method_exists($this, $sMethod)) { /** * Run the command */ return $this->$sMethod($aParameters); }
Просто используйте ReflectionMethod :
/** * Look for Command method */ if (method_exists($this, $sMethod)) { $reflection = new ReflectionMethod($this, $sMethod); if (!$reflection->isPublic()) { throw new RuntimeException("The called method is not public."); } /** * Run the command */ return $this->$sMethod($aParameters); }
Вы можете использовать функцию is_callable, чтобы определить, должен ли уровень защиты ограничивать вас: Пример:
<?php class FooBar { protected function Foo() { return; } public function Bar() { return; } } $foo = new FooBar(); var_dump(is_callable(array($foo, 'Foo'))); var_dump(is_callable(array($foo, 'Bar')));
Хотя вы не можете отличить, является ли метод приватным или защищенным, вы можете проверить, является ли public или нет внешним методом, использующим is_callable
. Я сравнил с ответом «мезе».
Так:
function testIfCallable($object, $method) { return is_callable(array($object, $method)); } function testIfCallable2($object, $method) { if (method_exists($object, $method)) { $reflection = new ReflectionMethod($object, $method); return $reflection->isPublic(); } return false; } class Test { private function privateMethod() { } protected function protectedMethod() { } public function publicMethod() { } public function testAccessibility() { if (testIfCallable($this, 'privateMethod')) echo "YYY<br>"; else echo 'NNN<br>'; if (testIfCallable($this, 'protectedMethod')) echo "YYY<br>"; else echo 'NNN<br>'; if (testIfCallable($this, 'publicMethod')) echo "YYY<br>"; else echo 'NNN<br>'; } public function testAccessibility2() { if (testIfCallable2($this, 'privateMethod')) echo "YYY<br>"; else echo 'NNN<br>'; if (testIfCallable2($this, 'protectedMethod')) echo "YYY<br>"; else echo 'NNN<br>'; if (testIfCallable2($this, 'publicMethod')) echo "YYY<br>"; else echo 'NNN<br>'; } public function testSpeedAccessibility() { return $results = [ testIfCallable($this, 'privateMethod'), testIfCallable($this, 'protectedMethod'), testIfCallable($this, 'publicMethod') ]; } public function testSpeedAccesibility2() { return $results = [ testIfCallable2($this, 'privateMethod'), testIfCallable2($this, 'protectedMethod'), testIfCallable2($this, 'publicMethod') ]; } }
Метод testIfCallable
должен быть включен в общий класс или что-то подобное, что у вас есть в вашем собственном наборе инструментов, потому что глобальные методы не рекомендуются.
Я использую это в сочетании с магическими методами __get
и __set
для обеспечения общедоступного метода «get / set».
Тесты:
//Test functionality $t = new Test(); $t->testAccessibility(); $t->testAccessibility2(); //Test speed $start = microtime(true); for($i = 0; $i < 10000; $i++) { $t->testSpeedAccessibility(); } echo "Is Callable way: " . (microtime(true) - $start) . "ms<br>"; $start = microtime(true); for($i = 0; $i < 10000; $i++) { $t->testSpeedAccesibility2(); } echo "Reflection way: " . (microtime(true) - $start) . "ms<br>";
Выходы:
NNN NNN YYY NNN NNN YYY Is Callable way: 0.23506498336792ms Reflection way: 0.45829010009766ms
Последние мысли
Если вам нужно протестировать все возможности видимости, вы можете использовать только testIfCallable2
, поэтому ответ «meze». В противном случае мой путь примерно в два раза быстрее. Поскольку ваш вопрос был только между публикой или нет, вы могли бы воспользоваться этим. Говоря о том, что, если вы не используете его часто, разница незначительна.