I don't see any mention of "namespaces" on this page so I thought I would chime in. The instanceof operator takes FQCN as second operator when you pass it as string and not a simple class name. It will not resolve it even if you have a `use MyNamespace\Bar;` at the top level. Here is what I am trying to say:
## testinclude.php ##
<?php
namespace Bar1;
{
class Foo1{ }
}
namespace Bar2;
{
class Foo2{ }
}
?>
## test.php ##
<?php
include('testinclude.php');
use Bar1Foo1 as Foo;
$foo1 = new Foo(); $className = 'Bar1\Foo1';
var_dump($foo1 instanceof Bar1Foo1);
var_dump($foo1 instanceof $className);
$className = 'Foo';
var_dump($foo1 instanceof $className);
use Bar2Foo2;
$foo2 = new Foo2(); $className = 'Bar2\Foo2';
var_dump($foo2 instanceof Bar2Foo2);
var_dump($foo2 instanceof $className);
$className = 'Foo2';
var_dump($foo2 instanceof $className);
?>
## stdout ##
bool(true)
bool(true)
bool(false)
bool(true)
bool(true)
bool(false)
자료형 연산자
instanceof는 PHP 변수가 어떤 클래스에서 생성된 객체인지 확인할 때 사용합니다:
Example #1 클래스에 instanceof 사용하기
<?php
class MyClass
{
}
class NotMyClass
{
}
$a = new MyClass;
var_dump($a instanceof MyClass);
var_dump($a instanceof NotMyClass);
?>
위 예제의 출력:
bool(true) bool(false)
instanceof는 변수가 부모 클래스에서 상속받은 클래스인지 확인할 때도 사용할 수 있습니다:
Example #2 상속 클래스에 instanceof 사용하기
<?php
class ParentClass
{
}
class MyClass extends ParentClass
{
}
$a = new MyClass;
var_dump($a instanceof MyClass);
var_dump($a instanceof ParentClass);
?>
위 예제의 출력:
bool(true) bool(true)
객체가 클래스의 인스턴스가 아닌지 확인하려면, 논리 not 연산자를 사용할 수 있습니다.
Example #3 객체가 클래스의 인스턴스가 아닌지 확인하기 위해 instanceof 사용하기
<?php
class MyClass
{
}
$a = new MyClass;
var_dump(!($a instanceof stdClass));
?>
위 예제의 출력:
bool(true)
마지막으로, instanceof는 변수가 인터페이스를 구현한 클래스의 객체 인스턴스인지 확인하기 위해 사용할 수 있습니다:
Example #4 클래스에 instanceof 사용하기
<?php
interface MyInterface
{
}
class MyClass implements MyInterface
{
}
$a = new MyClass;
var_dump($a instanceof MyClass);
var_dump($a instanceof MyInterface);
?>
위 예제의 출력:
bool(true) bool(true)
보통 instanceof를 문자 클래스명에 사용하지만, 다른 객체나 문자열 변수와도 사용할 수 있습니다:
Example #5 다른 변수와 instanceof 사용하기
<?php
interface MyInterface
{
}
class MyClass implements MyInterface
{
}
$a = new MyClass;
$b = new MyClass;
$c = 'MyClass';
$d = 'NotMyClass';
var_dump($a instanceof $b); // $b is an object of class MyClass
var_dump($a instanceof $c); // $c is a string 'MyClass'
var_dump($a instanceof $d); // $d is a string 'NotMyClass'
?>
위 예제의 출력:
bool(true) bool(true) bool(false)
주의해야할 함정이 있습니다. PHP 5.1.0 이전에, instanceof는 클래스명이 존재하지 않으면 __autoload()를 호출했습니다. 추가로, 클래스가 적재되지 않으면 치명적인 오류가 발생했습니다. 이는 동적 클래스 참조를 사용하거나, 클래스명을 가지는 문자열 변수로 해결할 수 있습니다:
Example #6 PHP 5.0 intanceof에서 클래스명 찾기와 치명적인 오류 피하기
<?php
$d = 'NotMyClass';
var_dump($a instanceof $d); // no fatal error here
?>
위 예제의 출력:
bool(false)
instanceof 연산자는 PHP 5에서 추가되었습니다. 이전에는 is_a()가 사용되었지만, is_a()는 instanceof의 기능으로 인해 배제되었습니다. PHP 5.3.0부터 is_a()는 배제되지 않게 되었습니다.
참고: get_class(), is_a().
returns true for any ancestor class, not just immediate superclasses.
php -r "class Mammal{}; class Primate extends Mammal {}; class Human extends Primate{}; \$h=new Human(); echo (\$h instanceof Mammal)?'Yes':'no';"
Yes
I was getting frustrated by instanceof not taking a string for its first argument so I wrote this function that takes strings or objects for both args and deals with both classes and interfaces. I hope it's useful to someone.
<?php
/**
* @desc: replacement for instanceof that accept strings or objects for both args
* @param: Mixed $object- string or Object
* @param: Mixed $class- string or Object
* @return: Boolean
*/
function oneof($object, $class){
if(is_object($object)) return $object instanceof $class;
if(is_string($object)){
if(is_object($class)) $class=get_class($class);
if(class_exists($class)) return is_subclass_of($object, $class) || $object==$class;
if(interface_exists($class)) {
$reflect = new ReflectionClass($object);
return !$reflect->implementsInterface($class);
}
}
return false;
}
?>
If you want to test if a classname is an instance of a class, the instanceof operator won't work.
<?php
$classname = 'MyClass';
if( $classname instanceof MyParentClass) echo 'Child of it';
else echo 'Not child of it';
?>
Will always output
Not child of it
You must use a ReflectionClass :
<?php
$classname = 'MyClass';
$myReflection = new ReflectionClass($classname);
if( $myReflection->isSubclassOf('MyParentClass')) echo 'Child of it';
else echo 'Not child of it';
?>
Will output the good result.
If you're testing an interface, use implementsInterface() instead of isSublassOf().
Sometimes you want to typehint objects INSIDE an array, but I think you can't.
Instead, you can use this function to check the classes inside this array:
<?php
public checkObjectsArray(array $array, $classname, $strict = false) {
if (!$strict) {
foreach ($array as $element) {
if (!($element instanceof $classname)) {
return false;
}
}
}
else {
foreach ($array as $element) {
if (get_class($element) != $classname) {
return false;
}
}
}
return true;
}
?>
It seems like instanceOf is using a string comparison. Longer class names take longer to check in conditional statements
eg.
if ($f instanceOf HelloWorldTestClass)
is much slower than
if ($f instanceOf HWT)
You can use "self" to reference to the current class:
<?php
class myclass {
function mymethod($otherObject) {
if ($otherObject instanceof self) {
$otherObject->mymethod(null);
}
return 'works!';
}
}
$a = new myclass();
print $a->mymethod($a);
?>
Example #5 could also be extended to include...
var_dump($a instanceof MyInterface);
The new result would be
bool(true)
So - instanceof is smart enough to know that a class that implements an interface is an instance of the interface, not just the class. I didn't see that point made clearly enough in the explanation at the top.
The PHP parser generates a parse error on either of the two lines that are commented out here.
Apparently the 'instanceof' construct will take a string variable in the second spot, but it will NOT take a string... lame
class Bar {}
$b = new Bar;
$b_class = "Bar";
var_export($b instanceof Bar); // this is ok
var_export($b instanceof $b_class); // this is ok
//var_export($f instanceof "Bar"); // this is syntactically illegal
//var_export($f instanceof 'Bar'); // this is syntactically illegal
Response to vinyanov at poczta dot onet dot pl:
You mentionned "the instanceof operator will not accept a string as its first operand". However, this behavior is absolutely right and therefore, you're misleading the meaning of an instance.
<?php 'ClassA' instanceof 'ClassB'; ?> means "the class named ClassA is an instance of the class named ClassB". This is a nonsense sentence because when you instanciate a class, you ALWAYS obtain an object. Consequently, you only can ask if an object is an instance of a class.
I believe asking if "a ClassA belongs to a ClassB" (or "a ClassA is a class of (type) ClassB") or even "a ClassA is (also) a ClassB" is more appropriate. But the first is not implemented and the second only works with objects, just like the instanceof operator.
Plus, I just have tested your code and it does absolutely NOT do the same as instanceof (extended to classes)! I can't advise anyone to reuse it. The use of <?php is_instance_of ($instanceOfA, 'ClassB'); ?> raises a warning "include_once(Object id #1.php) …" when using __autoload (trying to look for $instanceOfA as if it was a class name).
Finally, here is a fast (to me) sample function code to verify if an object or class:
<?php
function kind_of (&$object_or_class, $class)
{
return is_object ($object_or_class) ?
$object_or_class instanceof $class
: (is_subclass_of ($object_or_class $class)
|| strtolower ($object_or_class) == strtolower ($class));
}
?>
Posting this so the word typeof appears on this page, so that this page will show up when you google 'php typeof'. ...yeah, former Java user.
Unfortunately the instanceof operator will not accept a string as its first operand. So I wrote this function. It does exactly the same (ie, successively checks identicalness, inheritance and implementation). Just on strings.
<?php
function is_instance_of($sub, $super)
{
$sub = (string)$sub;
$super = is_object($super) ? get_class($super) : (string)$super;
switch(true)
{
case $sub === $super; // well ... conformity
case is_subclass_of($sub, $super):
case in_array($super, class_implements($sub)):
return true;
default:
return false;
}
}
// testing
interface X {}
class A {}
class B extends A {}
class C extends B {}
class D implements X {}
$i = 'is_instance_of';
var_dump($i('A', 'A'), $i('B', 'A'), $i('C', 'A'), $i('D', 'X'));
?>
Cross version function even if you are working in php4
(instanceof is an undefined operator for php4)
function isMemberOf($classename) {
$ver = floor(phpversion());
if($ver > 4) {
$instanceof = create_function ('$obj,$classname','return $obj instanceof $classname;');
return $instanceof($this,$classname);
} else {
// Php4 uses lowercase for classname.
return is_a($this, strtolower($classname));
}
} // end function isMemberOf
Please note: != is a separate operator with separate semantics. Thinking about language grammar it's kind of ridicilous to negate an operator. Of course, it's possible to negate the result of a function (like is_a()), since it isn't negating the function itself or its semantics.
instanceof is a binary operator, and so used in binary terms like this
terma instanceof termb
while ! (negation) is a unary operator and so may be applied to a single term like this
!term
And a term never consists of an operator, only! There is no such construct in any language (please correct me!). However, instanceof doesn't finally support nested terms in every operand position ("terma" or "termb" above) as negation does:
!!!!!!!!!!!!!!term == term
So back again, did you ever write
a !!!!!!!!!!!!= b
to test equivalence?
I can confirm what thisbizness at gmail dot com said just below in PHP 5.2, furthermore, people looking to use this as a "if $a is not instance of A" for error throwing purposes or other, just type it like this:
<?php
if( !$a instanceof A ) {
throw new Exception( '$a is not instance of A.' );
}
?>
This also works if $a is not an object, or not even set (you will get an E_NOTICE if it isn't set though).
A note worth making is that if you are unsure of if class A is present when making this comparison, and you don't want to trigger the __autoload() magic method, scroll down for examples of how to get around this.
I was unsure about it at first since most other operators have their own negative (like !=) or they are/can be used as function calls (like !is_a()) but it is this simple. Hope it helps someone.
Until again!
Negated instanceof doesn't seem to be documented. When I read instanceof I think of it as a compairson operator (which I suppose it's not).
<?php
class A {}
class X {}
//parse error from !
if (new X !instanceof A) {
throw new Exception('X is not an A');
}
//proper way to negate instanceof ?
if (!(new X instanceof A)) {
throw new Exception('X is not an A');
}
?>
use this for cross-version development...
<?php
function is_instance_of($IIO_INSTANCE, $IIO_CLASS){
if(floor(phpversion()) > 4){
if($IIO_INSTANCE instanceof $IIO_CLASS){
return true;
}
else{
return false;
}
}
elseif(floor(phpversion()) > 3){
return is_a($IIO_INSTANCE, $IIO_CLASS);
}
else{
return false;
}
}
?>
