使用 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' ]) ) ); } echo ' ; 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=
""
/>
應用 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 ) ); } echo ' ; var_dump( $o ); echo ' |
;
$serialized_obj
= json_encode(
$o
);
?>
"serialized_obj"
name=
"serialized_obj"
type=
"hidden"
value=
"/
'/", '
"',
$serialized_obj
)?>"/>
沒有留言:
張貼留言