萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 網路程式設計 >> PHP 程式設計

PHP 陣列與物件雙向轉換完全指南:遞迴深度轉換、StdClass、ArrayObject 與現代最佳實務

核心轉換函數:遞迴深度轉換

<?php
/** 陣列遞迴轉物件 (支援多維、資源型別保護) */
function arrayToObject(mixed $data): object {
    if (!is_array($data)) return $data;
    $obj = new stdClass();
    foreach ($data as $key => $value) {
        $obj->$key = is_array($value) || is_object($value) 
            ? arrayToObject($value) 
            : $value;
    }
    return $obj;
}

/** 物件遞迴轉陣列 (支援 private/protected 屬性、資源型別跳過) */
function objectToArray(mixed $obj): array {
    if (is_object($obj)) {
        $obj = (array) $obj; // 將物件屬性轉為陣列 (含可見性標記)
    }
    if (!is_array($obj)) return [];
    
    $result = [];
    foreach ($obj as $key => $value) {
        // 處理 private/protected 屬性鍵名 (含 \0* \0 前綴)
        $cleanKey = ltrim($key, "\0*\0");
        if (is_resource($value)) continue; // 資源無法序列化,略過
        $result[$cleanKey] = is_array($value) || is_object($value)
            ? objectToArray($value)
            : $value;
    }
    return $result;
}
?>

簡易強制轉型 (單層、無遞迴)

<?php
$arr = ['a' => 1, 'b' => 2, 'c' => 3];

// 陣列 → 物件
$obj = (object) $arr;           // stdClass { a:1, b:2, c:3 }
$obj->a; // 1

// 物件 → 陣列
$arr2 = (array) $obj;           // ['a'=>1, 'b'=>2, 'c'=>3]

// 匿名類別建構 (PHP 7+)
$obj = new class($arr) {
    public function __construct(public array $data) {}
};
?>

StdClass 與匿名類別

<?php
// 傳統 StdClass
$andy = new StdClass();
$andy->a = 1; $andy->b = 2; $andy->c = 3;

// 匿名類別 (PHP 7+) - 可定義方法、介面、型別提示
$andy = new class {
    public int $a = 1;
    public string $b = 'test';
    public function sum(): int { return $this->a + 10; }
};
$andy->sum(); // 11

// 唯讀屬性 (PHP 8.1+)
$config = new class {
    public readonly string $appName = 'MyApp';
    public readonly int $version = 1;
};
?>

ArrayObject:陣列物件化、可迭代、可計數、ArrayAccess

<?php
$array = ['1' => 'one', '2' => 'two', '3' => 'three'];
$ao = new ArrayObject($array, ArrayObject::ARRAY_AS_PROPS);

// 像陣列一樣操作
echo $ao['1'];        // one
$ao['4'] = 'four';    // 新增
echo count($ao);      // 4
foreach ($ao as $k => $v) { echo "$k=$v\n"; }

// 取得原生陣列
$native = $ao->getArrayCopy();

// 進階:繼承 ArrayObject 自訂行為
class MyCollection extends ArrayObject {
    public function offsetSet($key, $value): void {
        if (!is_int($value)) throw new InvalidArgumentException('只允許整數');
        parent::offsetSet($key, $value);
    }
}
?>

資源消耗與效能對比

特性陣列物件
記憶體複製時完整複製 (Copy-on-Write 優化)參考傳遞,極省記憶體
存取速度極快 (HashTable 直接索引)略慢 (屬性查找、可見性檢查)
序列化原生支援需實作 Serializable/JsonSerializable
型別安全無 (PHP 8.0+ 僅型別提示)可定義嚴格型別、readonly、介面
適用場景資料集合、暫時資料、高頻讀寫領域模型、服務物件、狀態封裝

現代最佳實務建議

  1. DTO/Value Object: 使用 readonly class (PHP 8.1+) 定義不可變資料傳輸物件。
  2. 集合類別: 繼承 ArrayObject 或實作 IteratorAggregate + Countable 封裝陣列操作邏輯。
  3. 避免手動轉換: 使用序列化器 (Symfony Serializer、Laravel Resources) 自動處理物件↔陣列/JSON。
  4. 資源型別處理: PDOStatement、Stream、GD Image 等資源不可直接序列化,轉換時需特別處理或略過。
  5. JSON API: 直接 json_encode($object) (實作 JsonSerializable) 或 json_encode($array),無需中間轉換。
copyright © 萬盛學電腦網 all rights reserved