php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #29736 instanceof requires class to be loaded
Submitted: 2004-08-18 16:31 UTC Modified: 2006-04-03 14:01 UTC
Votes:2
Avg. Score:4.5 ± 0.5
Reproduced:2 of 2 (100.0%)
Same Version:0 (0.0%)
Same OS:0 (0.0%)
From: hans at velum dot net Assigned:
Status: Closed Package: Feature/Change Request
PHP Version: 5.0.1 OS: *
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: hans at velum dot net
New email:
PHP Version: OS:

 

 [2004-08-18 16:31 UTC] hans at velum dot net
Description:
------------
[pasted from messages on internals@ list]

I like the new $obj instanceof ClassName way of checking class / interface types, .... but this method does have one major drawback compared to the old is_a() approach:

  The class must be loaded in order to perform an instanceof check!

There are many situations where you do not want to have to load every class to see whether a returned object is a class of that type.  In particular for driver classes, the current model requires loading *every* possible driver in order to check to see which type of class was returned.

is_a() works great, but has been deprecated and is now generating E_STRICT errors.


Reproduce code:
---------------
[conributed by Sean Coates on internals@ list]

<?php

class Foo {}

$foo = unserialize('O:3:"Foo":0:{}');

echo '$foo is_a Foo? '. (is_a($foo, 'Foo') ? 'yes' : 'no') ."\n";
echo '$foo instanceof Foo? '. ($foo instanceof Foo ? 'yes' : 'no') ."\n";

?>

---- and ----

<?php

//class Foo {}

$foo = unserialize('O:3:"Foo":0:{}');

echo '$foo is_a Foo? '. (is_a($foo, 'Foo') ? 'yes' : 'no') ."\n";
echo '$foo instanceof Foo? '. ($foo instanceof Foo ? 'yes' : 'no') ."\n";

?>

Expected result:
----------------
$foo is_a Foo? yes
$foo instanceof Foo? yes

---- and ----

$foo is_a Foo? no
$foo instanceof Foo? no



Actual result:
--------------
$foo is_a Foo? yes
$foo instanceof Foo? yes

---- and ----

$foo is_a Foo? no

Fatal error: Class 'Foo' not found in 
/home/sean/phpdoc/scripts/tmp/is_a.php on line 8

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2004-08-19 01:28 UTC] helly@php.net
Can't reproduce:

marcus@frodo /usr/src/PHP_5_0 $ php -r 'function __autoload($name) { var_dump($name); } $x = NULL; var_dump($x instanceof test);'
make: `sapi/cli/php' is up to date.
string(4) "test"

Fatal error: Class 'test' not found in Command line code on line 1
marcus@frodo /usr/src/PHP_5_0 $ php -r 'function __autoload($name) { var_dump($name); eval("class $name {}");} $x = NULL; var_dump($x instanceof test);'
make: `sapi/cli/php' is up to date.
string(4) "test"
bool(false)

So the problem lies in unserialize() -> other bug
 [2004-08-19 02:40 UTC] hans at velum dot net
Well, no ... the problem that I am describing has nothing to do with unserialize().  That was just an example that Sean posted that illustrates how is_a() and instanceof differ.  I apologize if that wasn't clear.

You did reproduce the bug in your first example.

Simple reproduction:

<?php

$c = null;
print '$c instanceof PEAR_Error ? ' . ($c instanceof PEAR_Error);

?>

Will result in E_FATAL (no such class).  That's the problem.  is_a() has no such limitations, but is now deprecated.  This change suggestion/request is asking for a way to check whether a variable is an instance of a particular class/superclass/interface *without loading that class/interface*.

Hope that makes it clearer.

-Hans
 [2004-08-19 02:43 UTC] alan_k@php.net
The example was buggy, but the bug exists :)

php5 -r 'class Foo{} $f = unserialize("O:3:\"Foo\":0:{}"); var_dump(!($foo instanceof Bar));'

Bar could be a huge class, I dont want to load it just to check $f wasnt a instance of it?
 [2005-04-06 08:50 UTC] indeyets at gmail dot com
I'll try to summarize:

there is no easy way to check if class implements some interface. This is needed, when, for example, php-application has support for loading external classes.

external classes have to implement some interface. And check for this should happen BEFORE object creation. (for example, there might be a need for some specific constructor syntax).


PHP 5.0 allows to do the following things:
1). $parent = get_parent_class("SomeClassName"). This would be sufficient, if plugins _extend_ some base class. that's not our case - wouldn't work for interfaces
2). if ($obj instanceof "SomeInterfaceName") {}. This would work, if we could create object before the interface check. Wouldn't work for non-existen objects
3). reflection API. it can do the thing, but overhead (both in code and in resources) is too big
 [2006-04-03 14:01 UTC] tony2001@php.net
Fixed in PHP 5.1
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Tue Aug 26 07:00:02 2025 UTC