PHPとMYSQLの組み合わせは、webであればよくあります。
どちらも大抵のレンタルサーバーには、標準で組み込まれており、他の言語、データベースのインストールが禁止されていることが多いためです。
今回もPHPとMYSQLのお話ですが、今回はある意味使うかどうかはケースバイケースかなというお話です。
プログラムをやっていたら、一度はやってみようか思うことがあります。
それは、配列をMYSQLに保存することです。
PHPであれば、配列を利用することは多々あります。
例えばMYSQLからデータを読み取った場合、配列で出力されます。
いままでは、配列の1項目を、MYSQLの1項目として分解して保存していましたが、配列のまま保存できないかと思いました。
そのやり方を調べてみましたので、忘備録として記録いたします。
PHPの配列をMYSQLに保存する方法は大まかに2種類ありました。
MYSQLにPHPの配列は、そのままでは保存できません。
なぜならば、文字列はダブルクオーテーションまたはシングルクォーテーションで囲われていないといけないためです。
実際にやってみたら、arrayという文字列がカラムと誤認識されMYSQLエラーとなりました。
なので、PHPの配列をダブルクオーテーションまたはシングルクォーテーションで囲える形式に変換する必要があります。
ググってみたら、この変換する方法が大まかに2種類ありました。
それがこちらです。
- serialize()関数を使用する方法
- json_encode()関数を使用する方法
実際にやってみると、どちらもMYSQLへ保存し取り出した後に復号化できました。
ここで、疑問がわきました。
どちらの関数が配列のMYSQL保存に適しているのか?
ということで、特徴についてされに調べてみました。
(1)serialize()関数の特色
serialize()関数についてマニュアルを見てみると、「値の保存可能な表現を生成する」とありました。
要はPHPの配列であれば、MYSQLで保存できる形式に変換できるというものでした。
実際にやってみると、MYSQLへの保存ができました。
復号化も以下のようにテストしてみたらできました。
<?php
$table = array("no"=>1, "name"=>"テスト", "code"=>"abcde", array("01"=>1, "02"=>2, "03"=>3, array("a"=>1, "b"=>2, "c"=>3)));
// 変換
$value = serialize($table);
// 復号化
$restore = unserialize($value);
?>
日本語が混ざっていても、3次配列にしても復号化できたので、なかなか優れもののようです。
(2)json_encode()関数の特色
json_encode()関数についてマニュアルを見てみると、JSON形式に変換とありました。
JSON形式なので、本来の目的はブラウザ⇔サーバー間の非同期通信用です。
ですが、MYSQLに保存できる形式に変換されるため、MYSQL変換用にも使えます。
実際にやってみると、MYSQLへ保存できました。
復号化は以下のようにやればできました。
<?php
$table = array("no"=>1, "name"=>"テスト", "code"=>"abcde", array("01"=>1, "02"=>2, "03"=>3, array("a"=>1, "b"=>2, "c"=>3)));
// 変換
$value = json_encode($table);
// 復号化
$restore = json_decode($value, true);
?>
3次元配列であっても、復号化できたのでその辺はserialize()関数と同じでした。
ただ、日本語に関してはUTF-8でないとエラーになり変換できませんでした。
JSONはUTF-8にしか対応していないためです。
疑問:結局どっちがいいの?
どちらの関数も配列をMYSQLへ保存する形式に変換することはできます。
ならば、どっちがいいのか?について考察してみました。
(1)利便性はserialize()関数
どちらも3次元配列など配列の階層は問題なく変換できました。
ただ、日本語に関してはjson_encode()関数UTF-8しか変換できないため、serialize()関数のほうが汎用性が高いです。
(2)変換容量が小さくなるのはjson_decode()関数
変換後の文字数はjson_encode()関数のほうが若干少なくなります。
少しでも容量を減らす場合はjson_encode()関数のほうが分があります。
(3)速さは環境により異なる
変換速度についてググると、答えがまちまちでした。
json_encode()が速いという記事もあれば、serialize()関数のほうが速いという記事もありました。
どちらも実証実験の結果で書かれていたため、どちらが正しいかは何とも言えません。
ただ、PHPのバージョンで結果が異なるようでした。
これらを踏まえるとserialize()関数のほうが無難
私は大量データの場合を想定して、少しでも速いほうを選ぶのがよいと考えます。
ですが、どちらの関数が速いかは明確に判定できませんでした。
ならば、利便性の高いほうが使い勝手が良いです。
日本語の変換も想定するならば、serialize()関数のほうが無難であると考えます。
そもそもjson_encode()はそもそも非同期通信目的の関数に対し、serialize()は配列変換用の関数です。
用途から考えてもserialize()関数が良いといえます。
MYSQLに配列を保存する必要性とは。
当たり前のことですが、配列を変換してMYSQLで保存すると、MYSQLでの特定項目の検索が著しくむつかしくなります。
配列内に別の項目で同じ値が存在し得るからです。
MYSQLのレコードに、専用のメンバを用意するし値を代入して保存するほうが遥かに使い勝手が良いです。
では、なぜ配列のままMYSQLに保存するのか?
それは、配列の階層などその都度内容が変化する場合に対応ためです。
今回、配列数が10個であったり、100個であったり状況によって異なるものをMYSQLに保存するケースがありました。
MYSQLに専用のメンバを用意するには、上限を決めておかなくてはいけません。
ですが配列そのまま保存の場合、上限を決めなくても汎用的に保存できます。
無論、MYSQLに1回で保存できる物理的上限はありますが、文字列だけで上限を超える配列になることは設計上ありませんでした。
例えば、配列数が10~1000個になる想定がある場合、MYSQLに保存する場合、少なくとも1000個のメンバが必要になります。
ですが、1000メンバを記述するのは現実的ではありません。
メンテナンスが大変だからです。
それよりも配列のまま保存する場合、MYSQLのメンバは1つで済みます。
保存する情報の数量が可変する、保存する項目数が多いといった場合にMYSQLへの配列保存のほうが利便性が高いです。
無論過信は禁物です。
状況に合わせて柔軟にMYSQL設計することが肝要です。