在日常開發中,我們常常使用PDO 來操作數據庫,而PDOStatement::fetchObject提供了一種非常優雅的方式,可以將查詢結果直接映射到一個對像上。但如果想要進一步提升查詢的靈活性,比如支持複雜的數據處理或映射到自定義的數據結構,我們可以結合外部庫來實現更高級的查詢方式。
本文將介紹如何通過PDOStatement::fetchObject配合外部庫,打造更加靈活強大的查詢系統。
fetchObject方法允許你在從數據庫中提取數據時,直接將每一行數據封裝成一個對象實例。基本用法如下:
<?php
$pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'password');
$stmt = $pdo->query('SELECT * FROM users');
while ($user = $stmt->fetchObject()) {
echo $user->name . "\n";
}
?>
雖然簡單易用,但如果遇到更複雜的數據映射需求,比如屬性重命名、自動類型轉換或關係映射,僅靠fetchObject就略顯單薄了。
為了提升靈活性,可以使用像Atlas\Mapper或者輕量級的php-data-mapper之類的庫。不過在這裡,我們以簡單示例為主,自己快速寫一個基礎的實體映射器。
假設我們希望查詢users表,並且將每條記錄映射成一個User類實例,且能自動處理字段與屬性之間的小差異。
首先,定義一個簡單的實體類:
<?php
// src/Entity/User.php
class User
{
public int $id;
public string $username;
public string $email;
}
?>
然後,編寫一個基礎Mapper:
<?php
// src/Mapper/UserMapper.php
class UserMapper
{
public static function map(PDOStatement $stmt): array
{
$results = [];
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$user = new User();
$user->id = (int)$row['id'];
$user->username = $row['name']; // 數據庫字段是 name,映射到 username
$user->email = $row['email'];
$results[] = $user;
}
return $results;
}
}
?>
在應用中調用它:
<?php
require 'src/Entity/User.php';
require 'src/Mapper/UserMapper.php';
$pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'password');
$stmt = $pdo->query('SELECT id, name, email FROM users');
$users = UserMapper::map($stmt);
foreach ($users as $user) {
echo $user->username . " <" . $user->email . ">\n";
}
?>
通過這種方式,即使數據庫字段與類屬性名稱不同,也能靈活對應,還能方便地加入更多高級邏輯(如類型轉換、嵌套關係處理等)。
如果你的項目比較大,推薦引入PSR-4 標準的自動加載器,比如使用Composer 來管理這些類,這樣不用每次都require文件,提升開發效率。
在composer.json中添加:
{
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
然後運行:
composer dump-autoload
之後在PHP 文件裡就可以這樣用:
<?php
require 'vendor/autoload.php';
use App\Entity\User;
use App\Mapper\UserMapper;
// ...代碼同上
?>
如果需要查詢的數據一部分來自數據庫,一部分需要遠程補充(比如調用gitbox.net的API),也可以結合使用:
<?php
function fetchAdditionalData(int $userId): array
{
$json = file_get_contents("https://gitbox.net/api/userinfo/$userId");
return json_decode($json, true);
}
foreach ($users as $user) {
$extraData = fetchAdditionalData($user->id);
$user->profile_picture = $extraData['profile_picture'] ?? null;
}
?>
這樣,數據庫+ 外部接口的數據整合就變得十分自然且強大了!