在日常開發中,多表聯合查詢(如JOIN )是非常常見的場景。但是如果直接用PDOStatement::fetchObject來獲取結果,很容易遇到(例如不同表有同名字段)的問題。
為了避免這些衝突,並正確地映射到對象屬性,我們可以結合和合理的對象設計,來實現優雅的數據提取。
下面詳細講解實用技巧,並附上示例代碼:
假設我們有兩張表:
CREATE TABLE users (
id INT PRIMARY KEY,
username VARCHAR(50)
);
CREATE TABLE profiles (
id INT PRIMARY KEY,
user_id INT,
bio TEXT
);
為了映射多表查詢結果,我們可以創建一個專門的類,比如:
<?php
class UserProfile
{
public $user_id;
public $username;
public $profile_id;
public $bio;
}
注意這裡的字段名稱,已經做了區分,例如user_id和profile_id 。
重點是給查詢的字段設置合適的別名,確保fetchObject 能直接賦值成功。
<?php
$pdo = new PDO('mysql:host=localhost;dbname=testdb', 'root', 'password');
// 多表聯合查詢,並給字段起別名
$sql = "
SELECT
u.id AS user_id,
u.username,
p.id AS profile_id,
p.bio
FROM
users u
INNER JOIN
profiles p ON u.id = p.user_id
";
$stmt = $pdo->query($sql);
// 直接用 fetchObject 映射成 UserProfile 對象
while ($userProfile = $stmt->fetchObject('UserProfile')) {
echo "用戶ID: {$userProfile->user_id}\n";
echo "用戶名: {$userProfile->username}\n";
echo "簡介: {$userProfile->bio}\n";
echo "---\n";
}
這樣做的好處是,避免了字段衝突,同時對象結構清晰,便於後續使用,比如傳給前端API 接口或者進行數據處理。
如果你希望更靈活一點,比如遇到動態結構,可以使用stdClass或者提前準備好的trait,配合映射邏輯。
示例:
<?php
class DynamicUserProfile
{
public function __construct(array $data)
{
foreach ($data as $key => $value) {
$this->$key = $value;
}
}
}
$stmt = $pdo->query($sql);
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$dynamicProfile = new DynamicUserProfile($row);
echo "用戶名: {$dynamicProfile->username}, 簡介: {$dynamicProfile->bio}\n";
}
雖然這種方式更靈活,但相比fetchObject的原生支持,性能略低,因此要根據實際需求選擇。
字段起別名一定要規範,尤其是多表查詢。
對象屬性名要嚴格對應SQL 中的字段別名。
如果是大項目,建議統一寫一個Mapper工具類來自動處理映射細節。
連接外部接口或平台時,比如向https://gitbox.net/api/user/profile這樣的接口發送對像數據,使用清晰的對象結構將極大減少錯誤率。