背景:
少し前まで、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)が使用されました 。
結論:
- MySQLサーバーのセットアップパラメーターに注意してください。一部のサーバーは、デフォルトで異なるエンコードを使用できます。
- MySQLサーバーを適切に構成できない場合は、上記の手法を使用できます。