Skip to content

Instantly share code, notes, and snippets.

@bayleedev
Created January 28, 2013 20:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bayleedev/4658562 to your computer and use it in GitHub Desktop.
Save bayleedev/4658562 to your computer and use it in GitHub Desktop.
Determines if a given method name can be responded to. Classes with magic methods should extend the method. Originally, I was going to have the default `$visibility` to null and auto-detect if it was an internal class or not, but that turned out to be rather slow. (https://gist.github.com/4658402)
<?php
namespace foo\bar\baz;
use ReflectionClass;
use ReflectionMethod;
use Exception;
use BadMethodCallException;
error_reporting(-1);
class foo {
/**
* Will determine if a method can be called.
*
* @param string $method Method name.
* @param integer $visibility Visibility (1 for public, 2 for public and
* protected, and 3 for all visibility)
* @return bool
*/
public function respondsTo($method, $visibility = 0) {
$class = new ReflectionClass($this);
$types = array();
$types[0] = ReflectionMethod::IS_PUBLIC;
$types[1] = $types[0] | ReflectionMethod::IS_PROTECTED;
$types[2] = $types[1] | ReflectionMethod::IS_PRIVATE;
foreach ($class->getMethods($types[$visibility]) as $reflectMethod) {
if ($reflectMethod->getName() === $method) {
return true;
}
}
return false;
}
public function foo() {
return;
}
protected function foobaz() {
return;
}
}
class foobar extends foo {
protected $_magicMethods = array();
public function __construct() {
$this->_magicMethods = array(
'bar' => function() {
return;
},
'baz' => function() {
return;
}
);
}
public function __call($method, $args) {
if (in_array($method, $this->_magicMethods, 1)) {
return $this->foo();;
}
throw new BadMethodCallException;
}
/**
* Custom check to determine if our given magic methods can be responded to.
*
* @param string $method Method name.
* @param integer $visibility Visibility (1 for public, 2 for public and
* protected, and 3 for all visibility)
* @return bool
*/
public function respondsTo($method, $visibility = 0) {
return isset($this->_magicMethods[$method]) || parent::respondsTo($method, $visibility);
}
}
$foobar = new foobar();
var_dump(
$foobar->respondsTo('foo'), // true
$foobar->respondsTo('bar'), // true
$foobar->respondsTo('baz'), // true
$foobar->respondsTo('foobaz'), // false
$foobar->respondsTo('foobaz', 1) // true
);
@bayleedev
Copy link
Author

It might be faster to do ReflectionClass::getMethod instead and do visibility checks after, but I'll benchmark before submitting a pr if this is desired functionality.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment