當前位置: 首頁> 最新文章列表> 使用PDOStatement::fetchObject 返回嵌套對象的數據處理技巧

使用PDOStatement::fetchObject 返回嵌套對象的數據處理技巧

gitbox 2025-05-12

在日常使用PHP 和PDO 操作數據庫時, PDOStatement::fetchObject是一個非常方便的方法,它可以直接將查詢結果轉成對象。然而,默認情況下它只會創建,不會自動處理更複雜的。如果你希望結果中包含嵌套的對象,比如一個User對象裡面嵌套一個Profile對象,就需要稍微自己動手加工一下。

下面我們就一步步來看,如何實現這一目標。

示例背景

假設你有這樣兩張表:

 CREATE TABLE users (
    id INT PRIMARY KEY,
    name VARCHAR(100),
    profile_id INT
);

CREATE TABLE profiles (
    id INT PRIMARY KEY,
    bio TEXT,
    avatar_url VARCHAR(255)
);

你希望查詢出用戶數據,並且讓結果變成一個User對象,同時嵌套一個Profile對象。

例如希望得到類似這樣的結構:

 User {
    id => 1,
    name => 'Alice',
    profile => Profile {
        id => 2,
        bio => 'Hello world!',
        avatar_url => 'https://gitbox.net/uploads/avatar.jpg'
    }
}

第一步:定義好對應的類

我們需要為UserProfile創建PHP 類:

 class Profile {
    public int $id;
    public string $bio;
    public string $avatar_url;
}

class User {
    public int $id;
    public string $name;
    public Profile $profile;
}

第二步:查詢數據,包含Profile 信息

你可以使用JOIN 查詢,把兩個表的數據一次性取出:

 $sql = "
    SELECT 
        u.id AS user_id,
        u.name AS user_name,
        p.id AS profile_id,
        p.bio AS profile_bio,
        p.avatar_url AS profile_avatar_url
    FROM users u
    JOIN profiles p ON u.profile_id = p.id
";
$stmt = $pdo->query($sql);

第三步:用fetchObject 自定義處理嵌套

由於fetchObject默認只映射一層數據,我們需要自己動手組裝嵌套對象。可以這樣做:

 while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
    $user = new User();
    $user->id = (int) $row['user_id'];
    $user->name = $row['user_name'];

    $profile = new Profile();
    $profile->id = (int) $row['profile_id'];
    $profile->bio = $row['profile_bio'];
    $profile->avatar_url = $row['profile_avatar_url'];

    $user->profile = $profile;

    // 現在 $user 就是包含嵌套 Profile 的對象了
    var_dump($user);
}

小技巧:封裝成一個通用方法

如果你經常需要這樣處理,可以封裝成一個小工具函數:

 function mapRowToUser(array $row): User {
    $user = new User();
    $user->id = (int) $row['user_id'];
    $user->name = $row['user_name'];

    $profile = new Profile();
    $profile->id = (int) $row['profile_id'];
    $profile->bio = $row['profile_bio'];
    $profile->avatar_url = $row['profile_avatar_url'];

    $user->profile = $profile;

    return $user;
}

// 使用
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
    $user = mapRowToUser($row);
    var_dump($user);
}

結語

雖然PDOStatement::fetchObject本身不能直接創建嵌套對象,但通過手動賦值和封裝,可以非常靈活地實現複雜的數據結構映射。這種方式比簡單的數組處理更清晰、類型更安全,也更符合現代PHP 面向對象的開發習慣。

如果想進一步簡化,可以考慮結合ORM 工具(比如Eloquent、Doctrine)來自動處理這些映射,但對於輕量項目,這種手動映射方法已經非常夠用了!