I need to check whether a certain class extends or implements a particular interface.
Note that the class name is a variable string, ie, there won't be any instance of this class.
Users are supposed to select a class from a list of classes and the system is supposed to check whether the class implements a certain interface or not. The list of classes is variable (according to the PHP software currently running), some of these classes can be initialized and others cannot.
Here's the code I'm using:
function is_instance_of($obj,$cls){
if(is_string($obj))$obj=new $obj();
if(PHP_MAJOR_VERSION>4)return $obj instanceof $cls;
if(PHP_MAJOR_VERSION>3)return is_a($obj,strtolower($cls));
return false;
}
var_dump(is_instance_of('MyClass','IMyInterface')); // in theory, true
var_dump(is_instance_of('Closure','IMyInterface')); // FATAL ERROR
That last test shows up the following error:
Catchable fatal error: Instantiation of 'Closure' is not allowed in C:\Users\abcdefghijklmn\debug.php on line XX
Things I tried:
- Using
$obj=new @$obj();:- error is hidden but it still faults/dies. - Using
try{}catch(){}around offending block :- nothing different happens - Using
'class' instanceof 'class'(where $obj is a string) :- returnsfalseunconditionally
Please note that the mandatory class initialization used in this method...sucks. Creating instances means unnecessary memory consumption, loss in speed and more prone to errors (imagine some weirdo class that when instantiated without parameters it proceeds to destroy your HDD ;) ). So, if there's any other way, I'd simply love to know about it.
Edit: This is (hopefully) the final code:-
/**
* Cross-version instanceof replacement.
* @param object $obj The instance to check.
* @param stirng $cls The class/interface name to look for.
* @return boolean Whether an object extends or implements a particular class
* or interface.
* @link http://stackoverflow.com/questions/4365567/php-instanceof-over-strings-and-non-initializable-classes
*/
function is_instance_of($obj,$cls){
if(is_string($obj) || PHP_MAJOR_VERSION>4){
$rc=new ReflectionClass($obj);
return $rc->implementsInterface($cls);
}else{
if(PHP_MAJOR_VERSION>3)return is_a($obj,strtolower($cls));
return false;
}
}
if(PHP_MAJOR_VERSION>4)return $obj instanceof $cls;The conditional will prevent execution on PHP 4 and less, but the parser will still have to parse it... and I don't think it will be very happy about it.