is_a
Checks whether an object or class name is of a given type, or has it as a parent or interface.
is_a(mixed $object_or_class, string $class, bool $allow_string = false): bool- Added in PHP 4.2.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$object_or_class | mixed | An object instance, or a class name string when $allow_string is true. |
$class | string | The class or interface name to test against, fully qualified. |
$allow_stringoptional | bool= false | When false, a string first argument is rejected and no autoloader runs. |
Return value
booltrue if the object or class is of type $class or has $class as one of its supertypes, false otherwise.
Errors
Does not throw. A first argument that is neither an object nor an allowed string simply returns false.
Changelog
- PHP 5.3.9The allow_string parameter was added, letting a class name string be passed as the first argument.
is_a() is the function form of the instanceof operator, with one extra ability: given allow_string = true it can test a class name rather than an instance, which instanceof cannot do without an object or a variable holding the name.
It returns true for the exact class, for any ancestor class, and for any interface implemented anywhere up the chain. That last part is the difference from get_parent_class(), which sees only classes.
When to reach for it
- Validating a class-string configuration value: "is this string a class that implements
Handler?" — before you ever instantiate it. - Filtering a list of discovered class names down to those matching a contract.
- Type checks inside a callable where you receive
mixedand want a boolean rather than a thrown error.
What trips people up
The default for allow_string is false, the opposite of is_subclass_of(). Pass a class name without setting it and you get a silent false.
The $class argument is a plain string that is never resolved against use statements — write Handler::class, not 'Handler'. And traits are not types: is_a() always returns false for a trait name, no matter which classes use it. Use class_uses() there.
Example
When to use it
- Validating that a class name pulled from config implements the interface your factory requires.
- Filtering get_declared_classes() down to every class implementing a given contract.
- Checking a mixed value's type in a guard clause where a thrown TypeError would be too harsh.
Frequently asked questions
What is the difference between is_a and instanceof?
They give the same answer for objects, but is_a() can also test a class-name string when you pass true as the third argument. instanceof is faster and is the idiomatic choice when you already hold an object.
What is the difference between is_a and is_subclass_of?
is_a() returns true when the object is the class itself; is_subclass_of() returns false in that case and only reports strict descendants. Their allow_string defaults are also opposite.
Does is_a work with traits?
No. Traits are not types, so is_a() always returns false for a trait name. Use class_uses() or class_uses() combined with class_parents() to detect traits.
More examples
Validating a class name from configuration
MailHandler passes; stdClass exists but does not implement the contract; Ghost does not exist at all. Checking class_exists() first keeps the autoloader out of it for obviously bad names.
<?php
interface Handler { public function handle(): string; }
class MailHandler implements Handler {
public function handle(): string { return 'mailed'; }
}
foreach (['MailHandler', 'stdClass', 'Ghost'] as $name) {
$ok = class_exists($name) && is_a($name, Handler::class, true);
echo $name, ': ', $ok ? 'usable' : 'rejected', "\n";
}is_a versus instanceof versus traits
instanceof and is_a() agree on the interface. The trait check returns false from is_a() because traits are not types — class_uses() is the right tool. Non-objects and unknown names return false rather than erroring.
<?php
trait Loggable {}
interface Jsonish {}
class Doc implements Jsonish { use Loggable; }
$d = new Doc();
var_dump($d instanceof Jsonish, is_a($d, Jsonish::class));
var_dump(is_a($d, 'Loggable'));
var_dump(in_array('Loggable', class_uses($d), true));
var_dump(is_a(null, 'Doc'), is_a('not a class', 'Doc', true));
Discussion