將 PHP 陣列轉為字串存入資料庫(如設定值、標籤、擴展屬性),讀取時還原為陣列。本文改良原代碼,修正安全性與相容性問題。
<?php
/**
* 字串還原為陣列
* @param string \$data 經 array2string 輸出的字串
* @return array 還原後的陣列,空字串回傳空陣列
*/
function string2array($data) {
if ($data === '' || $data === null) return [];
// 移除 addslashes 加入的反斜線
$data = stripslashes($data);
// 安全:僅允許陣列結構,禁止物件/資源
$result = @unserialize($data, ['allowed_classes' => false]);
return is_array($result) ? $result : [];
}
/**
* 陣列序列化為字串
* @param array \$data 要儲存的陣列
* @param bool \$stripSlashes 是否先處理 magic_quotes_gpc(舊環境用)
* @return string 序列化並 addslashes 後的字串
*/
function array2string($data, $stripSlashes = true) {
if (empty($data)) return '';
if ($stripSlashes && get_magic_quotes_gpc()) {
$data = stripslashes_deep($data);
}
// serialize 輸出可直接儲存,配合 addslashes 防 SQL 注入
return addslashes(serialize($data));
}
/**
* 遞迴移除陣列所有值的反斜線
*/
function stripslashes_deep($value) {
if (is_array($value)) {
return array_map('stripslashes_deep', $value);
}
return stripslashes($value);
}
?>
<?php
$config = [
'site_name' => 'My Blog',
'tags' => ['php', 'laravel', 'docker'],
'settings' => ['debug' => true, 'per_page' => 15]
];
// 存入 DB
$str = array2string($config);
// $str 類似: 'a:3:{s:9:"site_name";s:8:"My Blog";s:4:"tags";a:3:{i:0;s:3:"php";...}}'
// 從 DB 讀出還原
$restored = string2array($str);
print_r($restored);
/*
Array
(
[site_name] => My Blog
[tags] => Array ( [0] => php [1] => laravel [2] => docker )
[settings] => Array ( [debug] => 1 [per_page] => 15 )
)
*/
?>
| 方案 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
| serialize + addslashes | PHP 原生、支援多維陣列、型別保留 | 二進位不安全、跨語言困難、含類別資訊 | 單一 PHP 專案、簡單設定儲存 |
| json_encode/json_decode | 跨語言通用、可讀性高、標準格式 | 不支援 resource/物件、數字索引重排 | API 介面、需前端共用、異構系統 |
| igbinary | 體積更小、速度更快、二進位安全 | 需安裝擴展、不支援物件循環引用 | 高效能快取、Session 儲存 |
eval() 極度危險,嚴禁用於不可信資料。unserialize(..., ['allowed_classes' => false]) 禁止物件實例化,防止 POP Chain 攻擊。TEXT 或 LONGTEXT,並設定合適字符集(utf8mb4)。