[PHP] serialize/unserialize関数

ページを移動しても、
変数や配列等を保持できる仕組みを作りたい。

serialize/unserialize関数を使うと簡単にできるらしい。

http://phpspot.net/php/pg%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%82%92%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AB%E4%BF%9D%E5%AD%98.html

○serialize関数

上記サイトのソースをそのまま。

<?php

$a = new A;
echo serialize($a);

class A{
  var $hash;
  function A()
  {
    $this->hash = array(
      "a"=>"b",
      "c"=>"d",
      "e"=>"f"
    );
  }
}

?>

で、実行すると結果は、

O:1:"a":1:{s:4:"hash";a:3:{s:1:"a";s:1:"b";s:1:"c";s:1:"d";s:1:"e";s:1:"f";}}

という文字列が出力される。

この文字列の構造は、

O:(クラス名の文字数):"(クラス名)":(プロパティの個数):{(プロパティの内容)}

ってなってるみたいです。

(プロパティの内容)は、

s:(プロパティ名の文字数):(プロパティ名);(型)[:(文字数/配列の要素数)]:(値);....
(型:s=string, a=array, d=double....)

という感じになってて、

配列の場合は(値)の部分が、

{(キー);(値);(キー);(値)....}

と並んでますね。

試しに、ソースを以下のように書き換えてあげると、

<?php

$a = new test;
echo serialize($a);

class test{
  var $aaa;
  var $hashed;
  function __construct()
  {
    $this->aaa = 2.4;
    $this->hashed = array(
      "america"=>"boston",
      "china"=>"denmark",
      "england"=>"france"
    );
  }
}

出力結果は以下のようになります。

O:4:"test":2:{s:3:"aaa";d:2.4;s:6:"hashed";a:3:{s:7:"america";s:6:"boston";s:5:"china";s:7:"denmark";s:7:"england";s:6:"france";}}

○unserialize関数

http://php.net/manual/ja/function.unserialize.php

serialize関数で作った文字列を、
元のオブジェクトに戻す関数。

上記ソースのはじめの部分を、
以下のように書き換える。

$a = new test;
print('a : ');
print_r($a->hashed);
print("<br />\n");
$ser_a = serialize($a);

$b = unserialize($ser_a);
print('b : ');
print_r($b->hashed);

(クラス部分はそのまま)

出力結果は、

a : Array ( [america] => boston [china] => denmark [england] => france )
b : Array ( [america] => boston [china] => denmark [england] => france )

serialize/unserialize関数で、
“$a”と同じ内容のオブジェクト、
“$b”ができたことを確認できました。

●使ってみる

これらを使って、ページを移動しても、
オブジェクトのプロパティを保持できる仕組みを作る。

“serialize.php”を開いた時に、
オブジェクトをserializeして一時ファイルに保存。
(一時ファイルの保存先として”tmp”ディレクトリを作成のこと)

ボタンを押すと”unserialize.php”に飛んで、
保存したものを読み出して、
unserializeしてプロパティを表示。
読み出し後は一時ファイルを削除。

=== serialize.php ===============
<?php
/*クラス部分を別ファイルにしてrequire*/
require_once 'test.php';

/*オブジェクトの立ち上げとシリアライズ*/
$a = new test;
$ser_a = serialize($a);

/*一時ファイル名を指定*/
$now = new DateTime();
$file_name = 'tmp/test_'.$now->format('ymd-his').'.txt';

/*一時ファイルへ書き込み*/
$file = @fopen($file_name, x) or die('書き込みエラー');
flock($file, LOCK_EX);
fwrite($file, $ser_a);
flock($file, LOCK_UN);
fclose($file);

print_r ($a->hashed);
print ("<br />\nオブジェクトを".$file_name.'に保存しました。');
?>

<!-- unserialize.phpへのリンク : formでファイル名渡す -->
<form method="POST" action="unserialize.php">
    <input type="submit" value="unserializeへ">
    <input type="hidden" name="file_name" value="<?=$file_name ?>">
</form>

=== unserialize.php ===============
<?php
require_once 'test.php';

if (empty($_POST['file_name']))
    die('ファイル名が指定されていません!');

$file_name = $_POST['file_name'];

/*ファイル名チェック(一時ファイル以外を削除しないための保険)
    "tmp/test_"で始まる文字列以外は認めない*/
if ( preg_match('|^tmp/test_|', $file_name) == 0 )
    die('ファイル名が正しくありません!');

/*一時ファイルから読み込み*/
$file = @fopen($file_name, r) or die('読み込みエラー');
flock($file, LOCK_SH);
$ser_b = fgets($file, 1024);
flock($file, LOCK_UN);
fclose($file);
unlink($file_name); // 読み込み後、一時ファイルを削除

/*unserializeして出力*/
$b = unserialize($ser_b);
print_r($b->hashed);
?>
<br />
<input type="button" onclick="location.href='serialize.php'" value="戻る">

=== test.php ===============
(上記プログラムのクラス部分そのまま)
カテゴリーphp

コメントを残す

メールアドレスが公開されることはありません。