
網站突然出現這樣的錯誤,頁面整個停住:
Fatal error: Uncaught Error: Cannot use object of type stdClass as array in /home/.../plugins/system/helix3/helix3.php:54意思是:程式用陣列的方式($data['title'])去讀取一個「物件」,PHP 不允許,執行就中斷了。這個錯誤不是 Joomla 專屬,WordPress 外掛、自己寫的 PHP 程式都會遇到,原因和解法都一樣。
物件和陣列,差在哪裡?
PHP 裡有兩種常見的「裝資料的容器」:
- 陣列(array):用中括號讀取,例如
$data['title']。 - 物件(object):用箭頭讀取,例如
$data->title。stdClass是 PHP 最基本、沒有任何功能的物件,常出現在json_decode()和資料庫查詢的結果裡。
兩者裝的資料可以一模一樣,但讀取的寫法不能混用:
$arr = ['title' => '網頁設計'];
echo $arr['title']; // 正確
echo $arr->title; // 錯誤:Attempt to read property "title" on array
$obj = new stdClass();
$obj->title = '網頁設計';
echo $obj->title; // 正確
echo $obj['title']; // 錯誤:Cannot use object of type stdClass as array反過來把陣列當物件讀,PHP 8 的訊息是 Attempt to read property "title" on array(PHP 7 是 Trying to get property ... of non-object),原因相同,只是方向相反。
最常見的原因:JSON 解碼時的第二個參數
從 API、資料庫欄位讀到 JSON 字串,用 json_decode() 轉換時,第二個參數決定你拿到的是物件還是陣列:
$json = '{"name":"小明","address":{"city":"基隆"},"tags":["web","seo"]}';
// 不加第二個參數:得到物件
$obj = json_decode($json);
echo $obj->name; // 小明
echo $obj->address->city; // 基隆
echo $obj->tags[0]; // web(JSON 的陣列仍然是 PHP 陣列)
// 第二個參數設成 true:得到陣列
$arr = json_decode($json, true);
echo $arr['name']; // 小明
echo $arr['address']['city']; // 基隆
echo $arr['tags'][0]; // web所以看到這個錯誤,先找出那份資料是從哪裡來的:
- 如果是
json_decode($json)出來的,改成json_decode($json, true),後面的程式就能繼續用[]。 - 或是反過來,不改
json_decode(),把後面的$data['name']改成$data->name。
兩種擇一,同一份資料從頭到尾用同一種寫法,比較不會出錯。
另外,JSON 格式錯誤時 json_decode() 會回傳 null,後面的程式一樣會出錯。PHP 7.3 以上可以加上 JSON_THROW_ON_ERROR,格式錯誤時直接丟出例外,比較容易除錯:
try {
$data = json_decode($json, true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
$data = [];
}Joomla 裡常見的情境
資料庫查詢:loadObjectList 與 loadAssocList
Joomla 的資料庫物件有好幾種讀取結果的方法,回傳的格式不一樣:
use Joomla\CMS\Factory;
$db = Factory::getContainer()->get('DatabaseDriver');
$query = $db->getQuery(true)
->select($db->quoteName(['id', 'title']))
->from($db->quoteName('#__content'))
->where($db->quoteName('state') . ' = 1');
$db->setQuery($query);
$rows = $db->loadObjectList(); // 每一筆是物件:$rows[0]->title
$rows = $db->loadAssocList(); // 每一筆是陣列:$rows[0]['title']只取一筆的 loadObject() 與 loadAssoc() 也是同樣的道理。
文章的圖片、連結欄位
Joomla 文章的圖片(images)、連結(urls)、顯示選項(attribs)在資料庫裡是 JSON 字串,要先解碼才能用:
$images = json_decode($item->images);
$intro = $images->image_intro; // 物件寫法
$images = json_decode($item->images, true);
$intro = $images['image_intro']; // 陣列寫法原文的狀況:Helix3 外掛
這篇文章舊版記錄的是 Joomla 3 的 Helix3 樣板框架:plugins/system/helix3/helix3.php 在某些情況下收到的 $data 是物件,程式卻用陣列的方式讀取。當時的解法是在使用前先統一轉成陣列:
$data = is_object($data) ? (array) $data : $data;這個思路到現在都適用(下一節會再說明),但不建議直接修改外掛或樣板的檔案,擴充套件一更新,改的地方就會被覆蓋。比較好的做法是:
- 先更新到最新版,這類錯誤通常已經被開發商修正。
- Helix3 是 Joomla 3 用的框架,Joomla 3 已經停止支援;JoomShaper 在 Joomla 4/5 對應的框架是 Helix Ultimate,建議連同網站一起升級。
- 真的需要暫時修改,記下改了哪個檔案、哪一行,每次更新後都要再檢查。
不確定拿到的是物件還是陣列時
Joomla 有些事件、WordPress 有些 filter,傳進來的資料依情況可能是物件、也可能是陣列。這時先統一格式再處理:
if (is_object($data)) {
$data = get_object_vars($data);
}
$title = $data['title'] ?? '';get_object_vars()和(array)轉型都只轉換第一層:$data['address']如果原本是物件,轉完還是物件。- 需要整份資料(包含裡面每一層)都變成陣列,可以用
json_decode(json_encode($data), true),但只適合單純的資料(例如 API 回傳的內容),效能也比較差。 - 只是想安全地讀一個值,可以用
??,例如$city = $obj->address->city ?? '';,中間任何一層不存在都會回傳空字串,不會出現錯誤。
WordPress 裡的例子
get_post()、get_posts()回傳的是WP_Post物件,要用$post->post_title,不能用$post['post_title'](錯誤訊息會是Cannot use object of type WP_Post as array)。$wpdb->get_results()預設回傳物件;第二個參數傳ARRAY_A就會變成陣列。- 用
wp_remote_get()呼叫外部 API 取得的 JSON,同樣要注意json_decode()的第二個參數。
global $wpdb;
$sql = "SELECT ID, post_title FROM {$wpdb->posts} WHERE post_status = 'publish' LIMIT 5";
foreach ( $wpdb->get_results( $sql ) as $row ) {
echo esc_html( $row->post_title ); // 預設:物件
}
foreach ( $wpdb->get_results( $sql, ARRAY_A ) as $row ) {
echo esc_html( $row['post_title'] ); // ARRAY_A:陣列
}除錯小技巧
不知道變數到底是物件還是陣列,印出來看最快:
var_dump($data);開頭寫 object(stdClass) 就是物件,array(...) 就是陣列。在正式網站上除錯,改用 error_log(print_r($data, true)); 寫進錯誤記錄,不要讓訪客看到,看完記得刪掉。
另外,PHP 8 對型別的檢查更嚴格,例如對物件使用 count() 會直接出錯。舊程式在 PHP 7 只是跳出警告、還能勉強執行的寫法,升級到 PHP 8 後可能變成整頁當掉,升級 PHP 前最好先在測試環境跑過一次。
延伸閱讀
- Joomla 白畫面(空白頁)怎麼辦?從錯誤記錄到擴充套件衝突的完整排查順序
- Joomla 樣板覆寫(Template Override)教學:不改核心,修改文章與模組的輸出
- WordPress functions.php 實用程式碼整理:10 個常用又安全的小技巧
外掛、樣板在 PHP 或系統升級後冒出錯誤,是舊網站很常見的狀況。正威網路行銷是 25 年經驗的基隆網頁設計工作室,提供客製化網頁設計與網站維護託管,歡迎來聊聊。







發表留言
還沒有人留言,歡迎第一個分享你的想法或問題。留言經審核後才會顯示,Email 不會公開。