PDOStatement::fetchObject is a very convenient function when using PDO for database operations. It can directly encapsulate query results into objects, reducing the hassle of manual assignment. However, if used improperly, it may also cause problems, resulting in program performance degradation or logic confusion.
This article will teach you how to use fetchObject correctly and efficiently to avoid loading duplicate data objects.
In PHP, the PDOStatement::fetchObject method can encapsulate a single row of data from the database query results into an instance of a class. The sample code is as follows:
<?php
$pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'pass');
$stmt = $pdo->query('SELECT id, name FROM users');
while ($user = $stmt->fetchObject()) {
echo $user->id . ': ' . $user->name . '<br>';
}
?>
By default, fetchObject returns a standard class ( stdClass ) object, and you can also specify the class name you want to instantiate.
If there are duplicate records in your query results, or the same data appears in multiple queries, and you instantiate the object directly through fetchObject every time, then the same data will appear and multiple different object instances will be created .
For example:
$user1 = $stmt->fetchObject();
$user2 = $stmt->fetchObject();
// even though user1 and user2 of id same,它们也是不同of对象
This duplicate instantiation not only wastes memory, but can also cause problems with inconsistent data state, especially in large projects or complex data association queries.
After each time an object is generated through fetchObject , check whether an object with the same ID already exists. If it exists, it will be reused and will not be recreated.
Example:
<?php
class User {
public $id;
public $name;
}
$pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'pass');
$stmt = $pdo->query('SELECT id, name FROM users');
$users = []; // 用来缓存已经加载of对象
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$id = $row['id'];
if (!isset($users[$id])) {
$user = new User();
$user->id = $row['id'];
$user->name = $row['name'];
$users[$id] = $user;
}
// If already exists,Reuse $users[$id]
}
This manual processing can ensure that the same data is instantiated only once.
It can be further automated by passing in the fetchObject into its own class and implementing ID checks in the class constructor.
for example:
<?php
class User {
private static $instances = [];
public $id;
public $name;
public function __construct() {
// Prohibit external direct new,use create method
}
public static function create($row) {
if (isset(self::$instances[$row['id']])) {
return self::$instances[$row['id']];
}
$obj = new self();
$obj->id = $row['id'];
$obj->name = $row['name'];
self::$instances[$row['id']] = $obj;
return $obj;
}
}
$pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'pass');
$stmt = $pdo->query('SELECT id, name FROM users');
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$user = User::create($row);
}
?>
Although fetchObject itself is created for lazy people to quickly build objects, it is worthwhile to control it a little when the project requires high performance and unified management of the object life cycle.
Sometimes, duplicate data appears because SQL queries are not well written. For example, if you do not deduplicate correctly when doing JOIN, it will cause the same main record to appear multiple times.
The correct way is to use DISTINCT , GROUP BY or subquery in SQL to control the returned data.
For example:
SELECT DISTINCT users.id, users.name
FROM users
LEFT JOIN orders ON orders.user_id = users.id
This can reduce the generation of duplicate records at the source of the data and fundamentally solve the problem.
Although using PDOStatement::fetchObject is convenient, you should pay attention to the uniqueness of the object. To sum up:
For large projects, it is recommended to cooperate with object cache or object pooling mode.
For small projects, rationally optimizing SQL can avoid most duplicate loading problems.
If stricter object management is required, you can consider manually encapsulating the fetchObject process.
If you want to learn more about PDO skills, or need a standard set of PHP data access layer encapsulation, it is recommended to visit https://gitbox.net/php-tutorials for more detailed cases and practices.