2012-02-02 15 views
8

私はシリアル化してMySqlデータベースに保存する大きなPHPオブジェクトを持っています。テーブルのエンコーディングはUTF-8であり、シリアル化されたオブジェクトのエンコーディングを保持するカラムはUTF-8です。シリアル化されたオブジェクトをMySqlデータベースに保存する

問題は、オブジェクトがフランス語文字を含むテキスト文字列を保持していることです。例えば

:私は、オブジェクトをシリアル化するとき

Merci d'avoir passé commande avec Lovre. Voici le récapitulatif de votre commande 

は、文字列を維持し、正しいフォーマットになっている直接再度アンシリアライズ。私は、MySQLデータベースにシリアライズされたオブジェクトを保存するとき

しかし、その後、再びそれを取得した文字列は次のようになり、それをアンシリアライズ:私は、データベース内のオブジェクトを格納するとき

Merci d'avoir passé commande avec Lovre. Voici le récapitulatif de votre commande 

何かがうまくいきません。

  • オブジェクトはORMを推進使用して格納されます。
  • 列タイプはtextです。
  • 文字列はHTMLファイルに格納され、読み込まれます。
+0

ファイルのエンコーディングとは何ですか? – alexn

+0

base_64でエンコードしようとすることはできますが、そうする必要はありません。データベース列はどのような型ですか? PHPでデータベース接続の設定を確認しましたか? –

+0

@ TheSilencerデータベースの列の種類はテキストです。データベース接続はPROPELを使用して行われます。 – Songo

答えて

10

serializeで作成された文字列はバイナリ文字列ですが、特定の文字セットエンコーディングはありませんが、バイト配列(1バイトは8ビットの1オクテット)にすぎません。

LATIN-1をエンコードしてデータベースにUTF-8エンコードのテキストフィールドに格納するように指定した場合、データベースはLATIN-1のエンコードを透過的にLATIN-1からUTF-8。 UTF-8は、一部の文字に対して文字あたり1バイト以上の文字を使用する文字セットエンコーディングです(たとえば、éなど)。

éの文字列は、éのUTF-8バイトシーケンスであるéとしてデータベースに格納されます。

データベースから必要なエンコーディングを指定せずにデータをフェッチすると、データベースはそれをUTF-8として返します。

unserializeには、バイナリ文字列が無効になるように変更されているため、問題があります。

代わりに、シリアル化された文字列を格納するときにエンコーディングを変更しないようにデータベースに指示する必要があります。右側の列の種類とエンコーディング(バイナリフィールドBLOB - Binary Large Object­MySQL Docsも参照してください。Binary Types­Propel Docsを参照)を選択すると、データベースからデータをフェッチすると、charset-encodingが元の形式に戻されます。最初のアプローチ(バイナリフィールド)は、探しているものと正確に同じであるため、より優れています。

すでにデータベースに誤った形式で格納されているデータについては、データを修正する必要があります。これを行うには、まずどの再エンコードが適用されたかを調べる必要があります。 charsetからcharsetを取得します。私はLATIN-1だと思いますが、保証はありません。現在のアプリケーションデータのエンコーディングとプロセスを調べて調べる必要があります。

見つけたら、UTF-8から元のエンコードに戻り値をエンコードします。

+0

私はあなたが言ったことを試して、列の型をBLOBに変換しましたが、それでも問題は解決しませんでした。しかし、私は、データベースからオブジェクトを取得した後でメッセージ自体を 'utf_decode'することに決めました。それは問題を解決しました。 – Songo

+0

既存のデータおよび/または新しいデータのために存続しますか?また、私は専門家でもありませんが、アプリケーション層のロジックコード内でエンコーディングを気にする必要がないように、データベースレイヤーを使った簡単なソリューションが必要であることは間違いありません。データベース層でそれを解決できない場合は、PHPの['Serializable'](http://php.net/Serializable)インタフェースもあり、コードをきれいに保つのに役立ちます。 – hakre

+0

私はまだ開発段階にありますので、私は既存のデータを持っていません。私はPROPEL設定をチェックして、接続にUTF-8を使用しています。多分私がそこに見逃したことがあるかもしれませんが、あなたが言及したSerializableインターフェイスを調べます。ご協力いただきありがとうございます。 – Songo

4

utf-8 どこでも使用してください。 - あなたが何かを見逃したように聞こえます。

あなたのケースでは、データベース接続(SET NAMESステートメントまたはmysql_set_charset())を使用して、正しい文字セットを設定するのを忘れてしまったと思いますが、コードを見ずに言い表せません。 )。

次はあなたが世話をする必要があり、すべてのポイントをリストUTF-8 all the way throughに完璧な答えを与えているchazomaticusからの引用、次のとおりです。

ストレージ:

  • は(utf8_unicode_ciを指定しますまたは 相当)すべてのテーブルの照合 とデータベースのテキスト列。 これにより、MySQLは物理的に格納され、 はUTF-8でネイティブに値を取得します。

検索:PHPで

  • は、どんなDBラッパーあなたは 使用中、あなたはUTF8に接続 文字セットを設定する必要があります。このようにして、MySQLは が元のUTF-8 からデータをPHPに渡すときに変換を行いません。あなたがDB ラッパーを使用しない場合、あなたはおそらく、あなたのUTF-8で 結果を与えることにMySQLを伝えるために クエリを発行する必要がありますことを * 注:SET NAMES 'utf8' (とすぐに接続されます)。

配信:

  • あなたは、クライアントに 適切なヘッダを提供するためにPHPを伝えるために持っているので、 テキストはUTF-8として解釈されます。 PHPでは、あなたはdefault_charset php.iniのオプションを使用するか、または手動で はちょうどより多くの仕事であるが、同じ 効果があり Content-Typeヘッダを自分で発行することができます。

提出:

  • あなたは ブラウザによってあなたに送られたすべてのデータはUTF-8になりたいです。 残念ながら、 への唯一の方法は、 accept-charset属性をすべて <form>タグに追加することです:<form ... accept-charset="UTF-8">
  • 注 W3C HTMLの仕様では、 クライアントがどんな に戻ってサーバに フォームを送信するデフォルトでは、サーバーが務め文字セット「必要がある」、これは 明らかにのみので、勧告、 明示的であることが必要であると言うこと各<form>タグごとに
  • その前に、あなたはまだ はあなたが ストアにそれを試みるか、どこでもそれを使用する前に、有効なUTF-8であるとして、すべて提出した文字列 を確認したいと思う、が
  • 。 PHPの mb_check_encoding()はトリックを行いますが、 ですが、宗教的に使用する必要があります。

処理:

  • これは、残念ながら、ハード 一部です。 UTF-8文字列を処理するたびに を確実に確認する必要があります。 これは安全です。 を実行する最も簡単な方法は、 PHPのmbstring拡張を広範に使用することです。
  • PHPの 文字列操作はデフォルトでは無効です。 UTF-8は安全です。 は正常なPHP文字列 操作(連結など)でも安全ですが、ほとんどの場合 相当のmbstring機能を使用する必要があります。
  • (読み:ない混乱 それを)何をやっている知っている に、あなたは本当にUTF-8 とどのようにそれは最低 可能レベルで動作を知っておく必要があります。 のリンクのいずれかをutf8.comからチェックしてください。 のリソースが必要な場合は、 をご覧ください。
  • はまた、私は にもかかわらず、 はどこか指摘しておかなければ、このように感じることが明白に見えるかもしれません:あなたが提供されますすべてのPHPやHTML ファイルが有効なUTF-8で をエンコードする必要があります。

あなたはUTF-8を使用する必要はありません - 重要な部分は何であるかもしれない文字セットとは独立して、どこでもに同じ文字セットを使用することです。とにかく変更が必要な場合は、utf-8を使用してください。

1

私は常にbase64_encode()を使用して電子メールデータを保管しています。 シリアル化されたデータは時々問題を引き起こしますが、base64値を使用した後は単純な文字だけが残ります。

1

シリアル化する代わりにjson_encodeを使用することを強くお勧めします。ある日、あなたはPHP以外の場所からそのデータを使用しようとしていて、JSONに格納しておけばどこでも読めるようになります。事実上すべての言語がJSONの解読をサポートしており、よく確立された標準です。

どこでもutf8を使用することについての答えが保持されます! :-D

+0

良い考えではありません:1。 2.クラスの型とメソッドが失われる –

+0

メソッドは途中で失われてしまいます。あなたは 'serialize'呼び出しでそれらを保存しません。 私を信じて、シリアル化されたものを保存するのはずっと悪い考えです。あなたは最終的に他の場所からそのものを読む必要があります。 クラスにデシリアライズする必要がある場合は、型を文字列として保存し、その後、jsonデータを正しいクラスにインスタンス化してフィールドとして返すvsプレーンjsonを返す。 –

関連する問題