I am aware that instanceof
is an operator and that is_a
is a method.
Is the method slower in performance? What would you prefer to use?
I am aware that instanceof
is an operator and that is_a
is a method.
Is the method slower in performance? What would you prefer to use?
Update
As of PHP 5.3.9, the functionality of is_a()
has changed. The original answer below states that is_a()
must accept an Object
as the first argument, but PHP versions >= 5.3.9 now accept an optional third boolean argument $allow_string
(defaults to false
) to allow comparisons of string class names instead:
class MyBaseClass {}
class MyExtendingClass extends MyBaseClass {}
// Original behavior, evaluates to false.
is_a(MyExtendingClass::class, MyBaseClass::class);
// New behavior, evaluates to true.
is_a(MyExtendingClass::class, MyBaseClass::class, true);
The key difference in the new behavior between instanceof
and is_a()
is that instanceof
will always check that the target is an instantiated object of the specified class (including extending classes), whereas is_a()
only requires that the object be instantiated when the $allow_string
argument is set to the default value of false
.
Original
Actually, is_a
is a function, whereas instanceof
is a language construct. is_a
will be significantly slower (since it has all the overhead of executing a function call), but the overall execution time is minimal in either method.
It's no longer deprecated as of 5.3, so there's no worry there.
There is one difference however. is_a
being a function takes an object as parameter 1, and a string (variable, constant, or literal) as parameter 2. So:
is_a($object, $string); // <- Only way to call it
instanceof
takes an object as parameter 1, and can take a class name (variable), object instance (variable), or class identifier (class name written without quotes) as parameter 2.
$object instanceof $string; // <- string class name
$object instanceof $otherObject; // <- object instance
$object instanceof ClassName; // <- identifier for the class
is_a
undeprecated? –
Kitchenmaid $class = 'Foo'; var_dump($obj instanceof $class);
–
Elvera is_a
vs the instanceof
operator is that is_a
will accept expressions for the second parameter, while instanceof wont. For example is_a($object, 'Prefix_'.$name)
works while $object instanceof 'Prefix_'.$name
doesn't –
Legumin instanceof
cannot take a string parameter as its first argument. Currently your description makes it sounds like it could. –
Kablesh is_a
you have to specify the complete namespace on the 2nd parameter, even if you import the class with use
. –
Leffler is_a($foo, Foo::class)
. At which point you don't need to (since you're dynamically creating the string). –
Elvera is_a
never should have been deprecated in the first place. It's a little late to fix it now though. The problem is that the instanceof
operator throws syntax errors in PHP 4, and since is_a
was deprecated at the exact same time as the operator was introduced it became impossible to write code for both PHP 4 and 5 without throwing an E_STRICT around. You can't even do if (version_compare(PHP_VERSION, 5) >= 0) { /* use instanceof */ } else { /* use is_a */ }
because it would still cause a syntax error in PHP 4. –
Tavarez instanceOf
developed to allow to take an object along with class name or class identifier as the second parameter ? –
Tucker is_a()
. This is by far the most pervasive example of premature optimization. So premature that avoidance is advised in comments before an iota of code is ever written. –
Coseismal Here is performance results of is_a() and instanceof:
Test name Repeats Result Performance
instanceof 10000 0.028343 sec +0.00%
is_a() 10000 0.043927 sec -54.98%
Test source is here.
php 7
there is no difference. –
Mango is_a()
and instanceof
is important, you shouldn't be using PHP in the first place. Use C, C++ or Rust instead. I use is_a()
when the first parameter is a string and instanceof
otherwise because I think it's more readable. –
Kekkonen instanceof
can be used with other object instances, the class's name, or an interface. I don't think that (Update: See https://gist.github.com/1455148)is_a()
works with interfaces (only a string representing a class name), but correct me if it does.
Example from php.net:
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'
outputs:
bool(true)
bool(true)
bool(false)
is_a
does work with interfaces the same way as instanceof
(I was going to say the same thing, but I checked it before submitting, and it does indeed work)... –
Elvera Besides the speed, another important difference is how they handle edge cases.
is_a($x1, $x2) // fatal error if x2 is not a string nor an object
$x1 instanceof $x2 // returns false even if $x2 is int, undefined, etc.
So, is_a() highlights possible bugs while instanceof suppresses them.
In regards to ChrisF's answer, is_a()
is no longer deprecated as of PHP 5.3.0. I find it's always safer to go by the official source for things like this.
With regards to your question, Daniel, I can't say about the performance differences, but part of it will come down to readibility and which you find easier to work with.
Also, there is some discussion about the confusion around negating an instanceof
check vs is_a()
. For example, for instanceof
you would do:
<?php
if( !($a instanceof A) ) { //... }
?>
vs the following for is_a()
:
<?php
if( !is_a($a, 'A' ) { //... }
?>
or
<?php
if( is_a($a, 'A') === FALSE) { //... }
?>
Edit Looks like ChrisF deleted his answer, but the first part of my answer still stands.
There is a scenario where only is_a()
works and instanceof
will fail.
instanceof
expects a literal class name or a variable that is either an object or a string (with the name of a class) as its right argument.
But if you want to provide the string of a class name from a function call it will not work and result in a syntax error.
However, the same scenario works fine with is_a()
.
Example:
<?php
function getClassName() : string
{
return "Foobar";
}
class Foobar
{
private $xyz;
}
$x = new Foobar();
// this works of course
var_dump($x instanceof Foobar);
// this creates a syntax error
var_dump($x instanceof getClassName());
// this works
var_dump(is_a($x, getClassName()));
This is based on PHP 7.2.14.
Here are performance results obtained from here:
instanceof
is faster.
Functions
function method_1($a = null) {
return is_object($a) && is_a($a, 'Example');
}
function method_2($a = null) {
return is_a((object) $a, 'Example');
}
function method_3($a = null) {
return $a instanceof 'Example';
}
Times (run 5000 times each)
0.00573397 // method_1(5)
0.01437402 // method_2(5)
0.00376201 // method_3(5)
The optimization is minimal. And micro-optimisations are never a real good answer, in front of the readability, understandability, and stability of the code.
(personally, I prefer instanceof
, but the choice is yours)
The main difference is the possibility to use a direct class name with instanceof
$a instanceof MyClass
is shorter than
is_a($a, MyClass::class)
(ok… it’s not trivial)
The syntactical coloration between instanceof
(language structure) and is_a
is useful too (for me). Letting function color to bigger operations.
And for single use in if
, instanceof
doesn’t need more parenthesis.
Note: Of course, instead of MyClass::class
you can use a shorter direct string:
is_a($a,'MyClass')
But use direct string in a code isn’t a good practice.
The syntactical coloration is better and more useful if you can make a difference between simple string and class names.
And it's easier to change names with constant class names. Especially if you use a namespace with an alias.
So, why use is_a()
?
For the same reason: readability and understandability, the choice is yours.
Especially when used with !
or other boolean operators: is_a
seems more practical with parenthesis.
if ($a && (!is_a ($a, MyClass::class) || is_a ($a, MyOtherClass::class)))
is more readable than:
if ($a && (!($a instanceof MyClass) || ($a intanceof MyOtherClass)))
Another good reason is when you need to use a callback in functions, like array_map
...
instanceof
isn’t a function, it’s a language construct, so you cannot use it as a callback.
In those cases, is_a
may be useful.
I can't speak for performance -- I haven't measured anything yet -- but depending on what you are attempting, there are limitations with instanceof
. Check out my question, just recently, about it:
PHP 'instanceof' failing with class constant
I've ended up using is_a
instead. I like the structure of instanceof
better (I think it reads nicer) and will continue to use it where I can.
One interesting thing to note about is_a(): If you're using autoloader, namespaces and aliases for your classes, you'll need to use the true and full name of your class on is_a() because the method will not understand quite well what is what on your context. instanceof, on the other hand, understands it.
For instance (no pun intended):
<?php
namespace MyNamespace;
use \MyNamespace\User;
use \MyNamespace\Thing as Something;
class Test
{
public function doTest()
{
$user = new User();
var_dump(is_a($user, "User")); // false
var_dump(is_a($user, "\MyNamespace\User")); // true
var_dump($user instanceof User); // true
var_dump($user instanceof \MyNamespace\User); // true
}
public function doAnotherTest()
{
$something = new Something();
var_dump(is_a($something, "Something")); // false
var_dump(is_a($something, "\MyNamespace\Thing")); // true
var_dump($something instanceof Thing); // true
var_dump($something instanceof \MyNamespace\Thing); // true
}
}
© 2022 - 2024 — McMap. All rights reserved.