In PHP, the is_a() function is a practical tool for determining whether an object belongs to a certain class or its subclass. This function is usually used for type checking, especially in object-oriented programming modes such as polymorphic operations, dependency injection, object factories, etc. However, after the object has undergone the process of serialization ( serialize() ) and deserialization ( unserialize() ), the judgment mechanism of is_a() has some noteworthy behaviors and details. This article will discuss it in depth with actual examples.
class Animal {}
class Dog extends Animal {}
$dog = new Dog();
var_dump(is_a($dog, 'Dog')); // true
var_dump(is_a($dog, 'Animal')); // true
var_dump(is_a($dog, 'stdClass')); // false
is_a() accepts two parameters, the first is the object and the second is the class name (string). Returns true if the object is an instance of that class or its subclass.
serialize() in PHP converts the object into a string form and can be restored through unserialize() . Here are the basic examples:
$dog = new Dog();
$serialized = serialize($dog);
$unserialized = unserialize($serialized);
var_dump(is_a($unserialized, 'Dog')); // true
At this time, even if the object has been serialized and deserialized, as long as the class definition still exists, is_a() can still correctly judge the object's class.
The key to deserialization lies in the definition of the class. If the class is not available during deserialization, PHP will restore it to __PHP_Incomplete_Class . At this time, is_a() judgment will be invalid:
$serializedDog = 'O:3:"Dog":0:{}'; // From serialize(new Dog())
file_put_contents('dog.txt', $serializedDog);
// Assume that the following code is not defined when running Dog kind
$unserialized = unserialize(file_get_contents('dog.txt'));
var_dump(is_a($unserialized, 'Dog')); // false
var_dump(get_class($unserialized)); // __PHP_Incomplete_Class
is_a() cannot recognize incomplete class objects. Therefore, it is necessary to ensure that the relevant classes have been defined or automatically loaded before deserialization.
Modern PHP projects use PSR-4 or similar specifications to implement automatic loading mechanisms. For example, through Composer:
spl_autoload_register(function ($class) {
include 'classes/' . $class . '.php';
});
As long as the class file is loaded correctly before accessing is_a() or unserialize() , the judgment will work normally. Conversely, if the class is undefined, is_a() will always return false .
In some applications, serialized objects are transmitted across systems, such as API communications or task queues. Consider the following code:
$dog = new Dog();
$data = serialize($dog);
// Assume that API send
$url = 'https://m66.net/api/receive';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POSTFIELDS, ['payload' => $data]);
curl_exec($ch);
The receiver must ensure that the Dog class exists, otherwise it will not be possible to use is_a() to determine the object type correctly:
// Receiver code snippet
$data = $_POST['payload'];
$obj = unserialize($data);
if (is_a($obj, 'Dog')) {
// Logical processing
} else {
// Error handling
}
To avoid errors, a whitelisting mechanism should be used to prevent unserialized objects from being deserialized.
is_a() can effectively judge the object's class or its parent class;
Type information can still be retained after object serialization and deserialization, as long as the class exists;
If the class definition is missing, unserialize() will generate __PHP_Incomplete_Class , resulting in the failure of is_a() judgment;
Always load relevant classes before using deserialization;
For object data transmitted or persisted across systems, the classes and deserialization logic should be verified carefully to prevent security vulnerabilities.
Correct use of is_a() and serialization mechanisms can not only improve the robustness of the code, but also provide guarantees in terms of system scalability and security.