質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.96%

PHP7.1でMySQLの文字化けをなくしたい

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 3,928

score 18

PHP5.3.3からPHP7.1に移行しようとしているのですが、その際にMySQLの文字化けが治らず困っています。

MySQLのバージョンは5.1.73-logなのですが、最初に照合順序をlatin1_swedish_ciで作ってしまった後、utf8_general_ciに修正したのですが、現行環境のPHP5.3.3からアクセスした時のみ正常に表示されるものの、ターミナルやphpMyAdminから表示したら文字化けします。
イメージ説明

下記のようなのコードだとPHP5.3.3環境下での出力結果はこうなりますが

ダミーテキスト

PHP7.1.15だとこうなります

ダミーテキスト

<?
define("MYSQL_SERVER", "ip.add.re.ss");
define("MYSQL_DATABASE", "database");
define("MYSQL_USER", "user");
define("MYSQL_PASS", "pass");

// データベースに接続する
try{
    $pdo = new PDO("mysql:dbname=".MYSQL_DATABASE.";host=".MYSQL_SERVER , MYSQL_USER, MYSQL_PASS);
}
catch(PDOException $e){
    die("<h3>データベース接続エラー</h3>");
}

$sql = "SELECT `subject` FROM `page` WHERE `id`=1";
$st = $pdo->prepare($sql);
$st->execute();
$row = $st->fetch();

echo $row['subject']; //このカラムの中身は「ダミーテキスト」
?>

pdo接続でPHP7.1.15などの環境下でも文字化けしないようにするにはどうすればいいでしょうか?

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • m.ts10806

    2018/03/23 15:12

    DBをutf8_general_ciで作り直してデータを移行するというのは考えてないですか?

    キャンセル

  • schwarzewald

    2018/03/23 15:33 編集

    phpMyAdminで一度照合順序をutf8_general_ciに変更しても変わらなかったのですが、それとは別に新しくDBを作ってそこにデータを移し替えるということでしょうか?既にDBの中身が50GB近くあるのでちょっと難しいかなと…

    キャンセル

  • m.ts10806

    2018/03/23 15:58 編集

    なるほど。おおよそ原因が明らかであるため、原因探ってコードでなんとかするより新しくDB作って移し変えて向き先だけ変えたほうが早くに解決するとは思ったのですが、そう簡単でもない感じですね。

    キャンセル

  • schwarzewald

    2018/03/23 16:05

    最終的にはそうするしかないかなという感じですが、現在稼働中のシステムなのでどうやって移行するかが問題ですね…

    キャンセル

回答 3

check解決した方法

0

その後の顛末を報告します。
結局元のデータベースの文字化けを解決した方が良さそうなので解決策を探したところ、こちらの方法が見つかりました。
https://portalshit.net/2016/11/06/salvage-content-from-broken-mysqldump

結論から言えば、この通りに試してみたところ文字化けの大半は解決しました。
ただ、途中に絵文字などの4バイト文字が含まれているフィールドがその文字から先が消えてしまうなどの事態が発生してしまいました。

この方法を使う場合は一度mysqldumpしてから文字コードや照合順序をutf8mb4に変更した上でutf8mb4に対応したMySQLにリストアした上で行った方がいいかもしれません(それでエラーが発生しないのか未検証ですが…

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/09 19:40 編集

    utf8mb4 にした上で、スクリプト側の対応も必要。

    キャンセル

0

両方のバージョンのphp.iniで比較してみると何かわかるかもしれません。
例えば、

default_charset
mbstring.internal_encoding
mbstring.language

あるいはデータベースとのやり取り上のことであれば、
MySQLとPDOの組み合わせでcharsetを指定する - Qiita
を参考にPDO接続する際にcharset指定してみるとか。

また、照合順序の変更に関しては
MySQLの照合順序を修正する - Qiita
みたいな話もありますがここはOKでしょうか。

なお、質問文で示された文字化けの仕方は、
UTF-8(BOMなし)で「ダミーテキスト」をファイル保存したものを、
西ヨーロッパ言語(コードページ1252、iso-8859-1)として扱っているようです。
参考になるでしょうか。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/03/23 18:48

    ありがとうございます。

    php.iniについては、default_charsetの記述に以下のような違いがありました。

    5.3.3
    ; PHP's default character set is set to empty.
    ; http://www.php.net/manual/en/ini.core.php#ini.default-charset
    ;default_charset = "iso-8859-1"

    7.1.15
    ; PHP's default character set is set to UTF-8.
    ; http://php.net/default-charset
    ;default_charset = UTF-8

    どちらもコメントアウトされていて指定されていないようですが、デフォルトでは5.3.3が無指定、7.1.15の方がUTF-8という違いがあることが分かりました。
    そこでdefault_charset = UTF-8にしてみたり空欄にしてみたりしましたが、結果に変化はありませんでした。

    他の二項目は両方とも
    mbstring.internal_encoding = UTF-8
    mbstring.language = Japanese
    でした。

    それからPDO接続の際のcharset指定もやってみましたが変化はなく、照合順序も以前変更した時にすべてutf8_unicode_ciに変更していました

    キャンセル

0

更に追記です。
PHP5.3.6以降の環境で文字化けしたデータベースに接続する方法も分かりました。
SET NAMES latin1を指定してやれば文字化けせずにブラウザ上で表示することが出来ました。

$mysql_options = array(
    PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES latin1',
); 

// データベースに接続する
$spdo = new PDO("mysql:dbname=".MYSQL_DATABASE.";host=".MYSQL_SERVER , MYSQL_USER, MYSQL_PASS,$mysql_options);

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.96%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る