使用 PHP 的 serialize, compress 及 encode 函數,將 serialized object 儲存在網頁表單中。有 ASP.Net 使用經驗者,這即是 ViewState 的原理。
概論
PHP5 內建了一對 serialize 函數,即 serialize()/unserialize() ,可以將 object (a simple variable, an array, or an object which implement __sleep() method) 以特定字串形式儲存 (serialization)。此外,也可以用 JSON 形式,但需要安裝 php-json extension 才可支援。安裝 php-json 後,可用 json_encode()/json_decode() 進行 serialization 。
接下來,考慮到資料文字儲存在網頁時的傳送安全性以及儲存空間,再對 serialized object 進行資料壓縮及傳送編碼。
PHP 有兩組簡便的資料壓縮函數,即採用 ZLIB 壓縮格式的 gzcompress()/gzuncompress 和採用 DEFLATE 壓縮格式的 gzdeflate()/gzinflate() 。而 gzencode() 是前兩種壓縮格式的資料字串再加上 GZip file header 。我們並不需要 GZip file header ,在此不使用。由於 serialized object 係由一般文字組成,而 DEFLATE 壓縮格式對一般文字的壓縮率較佳,故採用 gzdeflate()/gzinflate() 。
壓縮後的字串,包含 binary 資料,直接儲存在網頁時,會破壞頁面結構,所以必須再加以編碼。 PHP 提供 MIME 的 base64 函數 base64_encode()/base64_decode() , base64 編碼格式只包含 A-Z,0-9, +, / 字元,不會破壞網頁的 HTML 語法,可安全地將資料儲存於網頁中。通常,我們利用網頁表單的隱藏欄位 (hidden input element in form) 儲存 serialized object ,以便隨著表單的提交送回 server 。
範例一
綜合以上說明,一個簡單的範例如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
if
( !isset(
$_POST
[
'serialized_obj'
]) ) {
$o
=
array
();
for
(
$i
= 0;
$i
< 100;
$i
++) {
$o
[
$i
] =
$i
*100;
}
}
else
{
$o
= unserialize( gzinflate(
base64_decode
(
$_POST
[
'serialized_obj'
]) ) );
}
var_dump(
$o
);
echo
'
'
;
echo
'Length of serialized object: '
,
strlen
(serialize(
$o
),
' '
;
echo
'Length of serialized object compressed by deflate: '
,
gzdeflate(
strlen
(serialize(
$o
)),
' '
;
echo
'Length of serialized object compressed by zlib: '
,
gzcompress(
strlen
(serialize(
$o
)),
' '
;
echo
'In most case, the length of data compressed by deflate will shorter than compressed by zlib. '
;
$serialized_obj
=
base64_encode
( gzdeflate( serialize(
$o
) ) );
?>
"serialized_obj"
type=
"hidden"
value=
""
/>
"postback"
type=
"submit"
>submit
應用 JSON
如果有需要利用 JavaScript 強化表單使用介面時,則可改用 json_encode()/json_decode() ,兼顧 server-side 的 PHP 及 client-side 的 JavaScript 。使用時須注意,根據 JSON 的規範,必須使用 UTF-8 字元編碼,故在非 UTF-8 環境下時,需先用 iconv() 將非 UTF-8 字元轉換成 UTF-8 字元。
最後要留意的事項是 magic_quotes_gpc 的影嚮。儲存在網頁表單中的 serialized object ,在提交回 server 時,若 magic_quotes_gpc 設定為 On ,則 PHP 會主動在 serialized object 的資料內容中加上必要的斜線字元 (slash, \) 。必須以 stripslashes() 將之去除,才可以 unserialization 。細心的人會注意到,在範例一,並沒有加上 stripslashes() 的動作。這並非失誤。因為範例一最後儲存的是 base64_encode() 的編碼字串,而這種格式的字串中,並未包含任何會被加上斜線字元的字元。亦即回傳的資料內容並不會受到 magic_quotes_gpc 的影嚮,所以並不需要 stripslashes() 。
範例二
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
if
( !isset(
$_POST
[
'serialized_obj'
]) ) {
$o
=
array
();
for
(
$i
= 0;
$i
< 100;
$i
++) {
$o
[
$i
] =
$i
*100;
}
}
else
{
if
( get_magic_quotes_gpc() ) {
$serialized_obj
=
stripslashes
(
$_POST
[
'serialized_obj'
]);
}
else
{
$serialized_obj
=
$_POST
[
'serialized_obj'
];
}
$o
= json_decode( preg_replace(
'/\\"/'
, "'",
$serialized_obj
) );
}
var_dump(
$o
);
echo
'
'
;
$serialized_obj
= json_encode(
$o
);
?>
"DropDownList1"
>
"serialized_obj"
name=
"serialized_obj"
type=
"hidden"
value=
"/
'/", '
"',
$serialized_obj
)?>"/>
"postback"
type=
"submit"
>submit