What is the difference between is_a and instanceof?
Asked Answered
F

10

228

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?

Ful answered 10/6, 2010 at 19:19 Comment(1)
is_a() could be slower - but you can call it using call_user_func() while instanceof cannot be called this way...Dashed
E
230

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
Elvera answered 10/6, 2010 at 19:26 Comment(15)
Why was is_a undeprecated?Kitchenmaid
@theodore-r-smith According to the documentation it "has been undeprecated by popular request" php.net/manual/en/migration53.undeprecated.phpInternuncial
instanceof can take either a string as parameter, object, or an identifier (class name written without quotes) @Elvera - can you provide an example for string as parameter ?Benuecongo
@danip $class = 'Foo'; var_dump($obj instanceof $class);Elvera
thanks, strange that var_dump($obj instanceof 'Foo') is not workingBenuecongo
@danip: correct, it can't be a constant string (and that would not make sense, since you could just use a literal identifier anyway)...Elvera
One more thing to note about 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'tLegumin
You should add that instanceof cannot take a string parameter as its first argument. Currently your description makes it sounds like it could.Kablesh
For is_a, if you set the third parameter to true, then parameter 1 sent to is_a can optionally be a string. instanceof does not have this flexibility.Yammer
Beware that with is_a you have to specify the complete namespace on the 2nd parameter, even if you import the class with use.Leffler
@ViniciusPinto unless you use is_a($foo, Foo::class). At which point you don't need to (since you're dynamically creating the string).Elvera
@Elvera very nice! this requires php 5.5+ thoughLeffler
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
@ircmaxell, In OOP , an object is an instance of a class. So why was instanceOf developed to allow to take an object along with class name or class identifier as the second parameter ?Tucker
"is_a will be significantly slower [...] but the overall execution time is minimal in either method." LOL, which one is it? There's this ridiculous conception among many developers that function calls are slow and therefore bad. Meanwhile, rarely does this trope surface for OOP in general where object instantiation is a thousand times more expensive than the minimal overhead of a function call, especially one as trivial as 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
L
57

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.

Liu answered 1/1, 2014 at 15:12 Comment(7)
In other words, the difference is only important if you need to save ~0.015 seconds per 10000 uses.Bourke
As of php 7 there is no difference.Mango
@CJDennis By experience, when everybody think like this, the final product will be slower than expected. (Soft + OS + servers unoptimized). Remember that time added is not always linear, but can be exponential. Always have perfomance in mind.Cheesy
@Cheesy There is a excellent blog post about what experienced developers can learn from beginners. Hopefully you can see it at the top right. Beware of premature optimisation! Only solve timing problems after they've become problems! If the performance is acceptable as it is, don't spend time changing it!Bourke
@CJDennis "Avoid premature optimization" is a good rule when there is a cost to pay in terms of development time. When writing new code, you might as well keep best practices in mind regarding performance, especially when they don't require any extra effort.Nit
@Nit How much development time would go into checking the difference? If it's more than 0.015 seconds, it's not worth it.Bourke
If you think that runtime performance difference between 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
M
9

instanceof can be used with other object instances, the class's name, or an interface. I don't think that is_a() works with interfaces (only a string representing a class name), but correct me if it does. (Update: See https://gist.github.com/1455148)

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)
Maiocco answered 10/6, 2010 at 19:24 Comment(2)
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
-1 please summarize the update rather than just linking to a gist. That is unhelpful for people trying to learn.Wage
C
8

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.

Consolidate answered 7/10, 2016 at 0:31 Comment(0)
U
7

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.

Unrepair answered 10/6, 2010 at 19:42 Comment(0)
D
7

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.

Dundalk answered 20/7, 2019 at 13:20 Comment(0)
C
2

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)
Copyist answered 3/11, 2014 at 4:49 Comment(0)
N
2

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.

Network answered 2/10, 2015 at 10:54 Comment(0)
M
1

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.

Mcgowen answered 10/6, 2010 at 19:30 Comment(0)
T
1

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
    }
}
Trichomonad answered 6/1, 2022 at 17:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.