Though you can not differentiate if the method is private or protected, you can test if public versus not using an external method using is_callable
. I made a comparison with "meze" answer.
So:
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')
];
}
}
The method testIfCallable
shall be included in a Common class or something similar which you have in your own toolkit because global methods aren't recommended.
I use this in conjunction with the magic methods __get
and __set
to ensure a public "get/set" method exists.
Tests :
//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>";
Outputs:
NNN
NNN
YYY
NNN
NNN
YYY
Is Callable way: 0.23506498336792ms
Reflection way: 0.45829010009766ms
Final thoughts
If you need to test between all the visibility possibilities, your only way to go is to use testIfCallable2
, so the "meze"'s answer. Otherwise, my way is about twice faster. As your question was only between public or not, you could benefit using this. Saying that, if you don't use it often, the difference is not significant.