2

UTF8 エンコーディングを使用し、特殊文字を含むユーザー名が多数含まれるデータベースに対して作業を行っています。

ユーザー テーブルをクエリすると、Lumen は誤ったデータで応答します。mysqliandを使用して同じテーブルにクエリを実行しようとしましたがPDO、期待どおりの結果が得られました。テストするためにサンプルルートを設定しました:

$app->get("charset", function() {
    $mysqli = new mysqli("localhost", "user", "password", "database");
    $res = $mysqli->query("select name from users where id = 1");

    $dbh = new PDO('mysql:host=localhost;dbname=database', "user", "password");
    $stmt = $dbh->query("select name from users where id = 1");

    $lumen = DB::select("select name from users where id = 1");

    return response()->json([
        "mysqli" => $res->fetch_assoc(),
        "pdo" => $stmt->fetchAll(PDO::FETCH_ASSOC),
        "framework" => $lumen
    ]);
});

ルートにアクセスすると、次の応答が返されます。

{
  "mysqli": {
    "name": "Ғђ ▫ Sony"
  },
  "pdo": [
    {
      "name": "Ғђ ▫ Sony"
    }
  ],
  "framework": [
    {
      "name": "Ò’Ñ’ â–« Sony"
    }
  ]
}

上記のテキストが正しく表示されない場合の応答のスクリーンショットを次に示します。壊れた UTF8 応答

私が知る限り、Lumen の MySQL 設定はデフォルトで UTF8 に設定されており、変更できませんvendor/laravel/lumen-framework/config/database

'mysql' => [
    'driver'    => 'mysql',
    'host'      => env('DB_HOST', 'localhost'),
    'database'  => env('DB_DATABASE', 'forge'),
    'username'  => env('DB_USERNAME', 'forge'),
    'password'  => env('DB_PASSWORD', ''),
    'charset'   => 'utf8',
    'collation' => 'utf8_unicode_ci',
    'prefix'    => env('DB_PREFIX', ''),
    'timezone'  => env('DB_TIMEZONE','+00:00'),
    'strict'    => false,
],

何が原因なのか途方に暮れています。この不一致を追跡するには、他に何ができますか?

4

1 に答える 1

1

この回答は、上記の私の以前のコメントに基づいています。

MySQL 接続文字セットは、MySQL クライアント (PHP) とサーバー間の通信に使用されるエンコーディングを定義します。実際の MySQL テーブルで内部エンコーディングとして使用されるエンコーディングは問題ではありません。MySQL サーバーは、テーブル エンコーディングと接続エンコーディングの間でデータを自動的に変換します。したがって、接続エンコーディングは基本的に、MySQL からデータを取得する際の形式と、MySQL にデータを挿入する形式を定義します。

データベースでデータが utf8 で正しくエンコードされていることを確認しますか?

ルーメン DB 接続に UTF8 のみを使用しているようですが (それがデフォルトの場合)、mysqli または PDO 接続の例では UTF8 を使用していません。$mysqli->set_charset("utf8");mysqli charset を使用して設定し、PDO charset を使用して設定した場合、同じ結果が得られますnew PDO('mysql:host=localhost;dbname=database;charset=utf8', "user", "password");か?

コードと出力例に基づいて、ルーメン DB 接続から UTF8 でデータを正しく取得しているように見えますが、出力は UTF8 として表示されません。

これは、mysqli と PDO の出力が UTF8 でデータを返さないため (接続文字セットを UTF8 に設定していないため) 正しく表示される理由も説明していますが、デフォルトでは、出力を表示しているエンコーディングと一致しているように見えます。 in (明らかに「latin1」または互換)。

Web ブラウザーで出力を表示している場合は、出力ページの文字セットが正しく定義されていることを確認してください (ヘッダーを使用するなど)。

編集:

ところで、接続エンコーディングが接続を介して送信されるデータのエンコーディングと一致する限り、データを挿入する他のシステムでどの接続エンコーディングが使用されているかは問題ではありません。

接続エンコーディングを latin1 に設定すると、SELECT を実行したときに文字列データが latin1 として取得されます。したがって、出力は UTF-8 ではなく latin1 として処理されるようです。出力環境 (Web ブラウザーなど) がサポートしている場合は、"as UTF-8" を正しく表示するようにスクリプト出力を修正した方がよいでしょう。そうしないと、latin1 で表示できない文字を処理する必要がある場合に問題が発生するためです。ただし、代わりに CLI ターミナル/コンソールに出力する場合は、もちろん、デフォルトのターミナル エンコーディングと同じエンコーディングを使用する必要があります (UTF-8 などでもかまいません)。Linux 端末も UTF-8 として構成することを好みます。

于 2015-05-19T12:35:22.937 に答える