Current Location: Home> Latest Articles> Implementing deep copying techniques for objects in PDOStatement::fetchObject

Implementing deep copying techniques for objects in PDOStatement::fetchObject

gitbox 2025-05-29

When using PHP's PDOStatement::fetchObject() method, we can usually conveniently map the database query results directly into objects. However, sometimes due to certain special needs (such as preventing reference issues), we want to get a copy of the object instead of a single instance object that is directly mapped. This article will introduce a simple and efficient method to achieve deep replication skills.

Problem background

Under normal circumstances, fetchObject() returns a new object of the query line, but if the object contains reference attributes inside, or the object copy is cached through other logic, it may lead to data leakage or modification conflicts.

For example:

 $stmt = $pdo->query('SELECT id, name FROM users');
$user = $stmt->fetchObject(User::class);

// Follow-up $user Modifications may affect other logic
$user->name = 'New Name';

To avoid this side effect, we hope that the object we get will be independent and irrelevant every time, and can be correctly disconnected even if the internal attributes are referenced.

Methods of deep replication

The most direct way to implement deep replication in PHP is to serialize and deserialize objects. Examples are as follows:

 function deepCopy($object) {
    return unserialize(serialize($object));
}

This deepCopy function ensures that the object and its internal properties are completely copied and no longer shared references.

Integrate deep replication into fetch process

We can slightly wrap the usage process of fetchObject() so that after each object is retrieved, deep copying is performed immediately:

 class UserRepository
{
    protected PDO $pdo;
    
    public function __construct(PDO $pdo)
    {
        $this->pdo = $pdo;
    }
    
    public function findAllUsers(): array
    {
        $stmt = $this->pdo->query('SELECT id, name, profile FROM users');
        
        $users = [];
        while ($user = $stmt->fetchObject(User::class)) {
            $users[] = $this->deepCopy($user);
        }
        
        return $users;
    }
    
    protected function deepCopy(object $object): object
    {
        return unserialize(serialize($object));
    }
}

In this example, we use deepCopy() to wrap the object retrieved from the database, ensuring that each element in the $users array is an independent copy.

Things to note

Although the serialization-deserialization method is simple and easy to use, there are several points to note:

  • Performance overhead : Serialized deep replication has a certain impact on performance, especially when processing large amounts of data, the impact should be evaluated.

  • Object Restrictions : If the object contains resource handles (such as database connections, file pointers, etc., which are not serializable, then serialization will fail.

  • Custom copy : If the object is complex, you can consider implementing the __clone() method to manually deep copy logic.

A more elegant gadget class

If you often need to copy objects in your project, you can encapsulate a tool class:

 class ObjectHelper
{
    public static function deepCopy(object $object): object
    {
        return unserialize(serialize($object));
    }
}

Then it is clearer when calling:

 $copy = ObjectHelper::deepCopy($user);

If you are interested, you can also publish this tool as a Composer package and upload it to your own private repository, such as https://gitbox.net/your-username/object-helper , which is convenient for reuse in multiple projects.

Summarize

The best trick to implement deep replication in PDOStatement::fetchObject() is to combine serialization to ensure that each object does not interfere with each other. Although it is necessary to pay attention to performance and object structure limitations, this method is simple, efficient and very practical in most small and medium-sized projects.

If you want to optimize further, you can also explore custom replication strategies based on reflection, but that's another topic!