萬盛學電腦網

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

PHP Fatal Error: Cannot use object of type stdClass as array 解決方案與物件/陣列轉換技巧

這是 PHP 開發中極高頻的錯誤:Cannot use object of type stdClass as array。當嘗試用陣列語法 $obj['key'] 存取物件屬性時觸發。本文解析產生原因、兩種標準解法,並延伸介紹物件與陣列互轉的最佳實務。

錯誤重現場景

<?php
$json = '[{"id":1,"title":"文章一"},{"id":2,"title":"文章二"}]';
$data = json_decode($json); // 預設回傳 stdClass 物件陣列

// 錯誤寫法
echo $data[0]['title']; // ❌ Fatal Error: Cannot use object of type stdClass as array

// 正確寫法
echo $data[0]->title;   // ✅ 輸出:文章一

兩種標準解決方案

方案一:json_decode($json, true) 直接產生關聯陣列 (最推薦)

$data = json_decode($json, true); // 第二參數 true = associative array
echo $data[0]['title']; // ✅ 正常運作
// 結構:[ ['id'=>1,'title'=>'文章一'], ['id'=>2,'title'=>'文章二'] ]

優點:直接得到陣列,後續處理統一使用陣列語法,無需物件轉換。

方案二:物件屬性存取語法 $obj->property

title; // ✅
// 甚至可鏈式存取
echo $data[0]->title . ' - ID: ' . $data[0]->id;

適用場景:需要利用物件特性(如方法、型別提示、序列化行為)時。

進階:物件 ⇄ 陣列 雙向轉換工具函式

<?php
/**
 * 任意物件/陣列 深度轉換為純陣列
 * @param object|array $data
 * @return array
 */
function toArray($data) {
    if (is_object($data)) $data = (array) $data;
    if (!is_array($data)) return [$data];
    
    return array_map(function($v) {
        return is_object($v) || is_array($v) ? toArray($v) : $v;
    }, $data);
}

/**
 * 陣列深度轉換為 stdClass 物件
 * @param array $arr
 * @return object
 */
function toObject($arr) {
    if (!is_array($arr)) return $arr;
    $obj = new stdClass();
    foreach ($arr as $k => $v) {
        $obj->$k = is_array($v) ? toObject($v) : $v;
    }
    return $obj;
}

// 使用範例
$objData = json_decode($json);
$arrData = toArray($objData);      // 物件樹 → 陣列樹
$objAgain = toObject($arrData);    // 陣列樹 → 物件樹

常見來源與預防

PHP 8.1+ 新語法:readonly 類別與 array_is_list()

<?php
// 定義資料傳輸物件 (DTO)
readonly class ArticleDTO {
    public function __construct(
        public int $id,
        public string $title,
        public string $content,
    ) {}
}

// 從陣列安全建構物件
function hydrateArticle(array $data): ArticleDTO {
    return new ArticleDTO(
        $data['id'] ?? 0,
        $data['title'] ?? '',
        $data['content'] ?? '',
    );
}

// 陣列判斷輔助
$arr = ['a', 'b'];
array_is_list($arr); // true
$obj = (object) $arr;
array_is_list((array)$obj); // true (鍵為 0,1 連續整數)

善用型別宣告與 DTO 模式,可在編譯/靜態分析階段(PHPStan、Psalm)攔截此類錯誤。

copyright © 萬盛學電腦網 all rights reserved
來源回傳型別建議處理
json_decode()stdClass / array習慣加 true 參數
SoapClient 回應stdClass用 toArray() 統一轉陣列處理
SimpleXMLElement物件json_decode(json_encode($xml), true) 快速轉陣列
PDO::FETCH_OBJstdClass改用 PDO::FETCH_ASSOC 直接拿陣列
MongoDB 驅動物件驅動選項 typeMap 設定陣列模式