MySQLからSymfonyへのデータのエンコードに関する問題の解決

私はすぐにSymfonyとDoctrineに不慣れであり、Symfonyを使用するときにこの種の問題に遭遇したのは初めてでしたが、私の経験は類似または類似の問題を解決するのに役立つと思います。



背景:



少し前まで、Symfony2上の特定のプロジェクトをホストプラットフォームにアップロードする機会がありましたが、よくあることですが、アプリケーションがライブサーバーで動作することを拒否し、デバッグを有効にすると、次の計画の通知が表示されました:



Twig_Error_Runtime:テンプレートのレンダリング中に例外がスローされました

( "警告:htmlspecialchars()[function.htmlspecialchars]:の引数の無効なマルチバイトシーケンス

/.../app/cache/prod/classes.php line ...”)in "..." at line ...




このエラーの理由は、 htmlspecialchars()関数の助けを含めて、Twigがデフォルトですべての出力をシールドするという事実にあります。この場合、 Invalid multibyte sequenceをトリップします 。 そして、この同じ無効なマルチバイトシーケンスを表示するのが良いと判断したので、次のような未加工のフィルターを介してテンプレート内の対応する変数の出力をスキップしました。

{{ sometext|raw }}





何らかの理由でデータベースからのキリル文字のテキストデータがcp1251エンコーディングで送られることが判明しましたが、インポートされたデータベース、テーブル、および応答のエンコーディングは異なります。 値が取得されたフィールドはutf8でした。 ホスティング事業者から提供されたphpMyAdminの[変数]タブで、mysqlサーバー構成パラメーターの次の値に注意が向けられました。

 init connect SET NAMES cp1251
照合データベースcp1251_general_ci
照合サーバーcp1251_general_ci
 ...


問題:



明らかに、理由はinit connectにあり、接続時にSET NAMES cp1251を実行したため、すべての値がcp1251としてアプリケーションに転送されました。

セット名
SET NAMESは、クライアントがサーバーにデータを送信するエンコーディングと、サーバーがクライアントに応答を送信するエンコーディングを定義することを思い出してください。




この種の問題は通常非常に簡単に解決されます。アプリケーションのデータベースに接続した直後に、次のタイプのリクエストまたはリクエストのグループを実行します。

SET CHARACTER SET UTF8;

SET NAMES UTF8;






しかし、私にとっては、データベースへの余分なクエリはまったく一般的ではなく、フレームワークコードにも松葉杖があります。 そのため、最初はテクニカルサポートを通じて問題の解決を試みました。

ホスト会社のテクニカルサポートのスタッフは、データベースをutf8用に構成されたサーバーに転送できないと言った。 使用するすべてのサーバーはcp1251で同じ構成になっており、1つのプロジェクトのためにサーバー設定を変更することはありません。

変更は、このサーバー上のすべてのデータベースに影響します(完全に理解しています)。 しかし、問題は何らかの形で解決する必要がありました...



解決策:



ただし、Symfonyの決定は非常にエレガントであることが判明したため、この記事を執筆したのはそのためです。

私を助けるために、小さなEventListenerが来ました。それをpostConnectイベントに掛けました。



作成するには、app / config / config.ymlファイルの「services」セクションにエントリを作成する必要があります(YAMLが使用されている場合):

 サービス:
     onconnect.listener:
        クラス:Dev \ SomeBundle \ EventListener \ OnConnect
        タグ:
              -{名前:doctrine.event_listener、イベント:postConnect} 




バンドルでは、上記の名前空間の構成( Dev \ SomeBundle \ EventListener \ OnConnect )で指定されたものと一致するリスナーファイルを作成する必要があります。

つまり OnConnect.phpファイルをDev / SomeBundle / EventListenerフォルダーに配置し、次のコンテンツを含めます。



 <?php //file src/Dev/SomeBundle/EventListener/OnConnect.php namespace Dev\SomeBundle\EventListener; use Doctrine\Common\Persistence\Event\LifecycleEventArgs; use Doctrine\ORM\EntityManager; class OnConnect { public function postConnect( $event ) { $conn = $event->getConnection(); $conn->executeQuery("SET NAMES UTF8"); } }
      
      







私の場合、エンコーディングの問題は完全に解消され、さらに、「ハック」をドクトリンまたはフレームワークコードに挿入する必要がなくなりました。 イベントリスナーは、さまざまなタスクを解決するためにSymfonyで広く使用されています。 上記の例では、 Symfony 2.2.0(Standard Edition)が使用されました



結論:



  1. MySQLサーバーのセットアップパラメーターに注意してください。一部のサーバーは、デフォルトで異なるエンコードを使用できます。
  2. MySQLサーバーを適切に構成できない場合は、上記の手法を使用できます。



All Articles