We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 28073
    • 164 Posts
    こんにちわ。
    多分kazuikeさんも僕と同じ現象のようです。

    modxのソース中にSET CHARACTER SETを指定しているところがあるのですが、その下にSET NAMES入れると文字化けは解消されると思います。
    ちなみにSET CHARACTER SETの手前にSET NAMESを書いてもダメでした(少なくとも僕の場合は)。

    この修正のほうがsql文の直前にSET NAMESを入れていくよりは楽だと思います。
    それでも結構修正箇所はありますが :’(
    (修正箇所は昨日お知らせしたURLのページに書いています)

    取り急ぎ連絡まで。
      • 15497
      • 117 Posts
      soushiさん、ありがとうございます。

      soushiさんに教えていただいたやり方で直ることは間違いないと思います。
      直そうかと思ったのですが、INSERTとUPDATEで違うというのが、どうも気持ちが悪くって、
      せっかくですので、直してしまう前にちょっと調べておこうと…

      とりあえず、「save_content.processor.php」のINSERTとUPDATEのそれぞれ直前で、
      MySQLの設定値がどうなっているか「SHOW VARIABLES LIKE ’character_set%’」で調べてみました。

      INSERTの直前(抜粋)

      character_set_client => utf8
      character_set_connection => ujis
      character_set_database => ujis
      character_set_results => utf8
      character_set_server => ujis
      character_set_system => utf8

      UPDATEの直前(抜粋)

      character_set_client => utf8
      character_set_connection => utf8
      character_set_database => utf8
      character_set_results => utf8
      character_set_server => ujis
      character_set_system => utf8

      なんと、「character_set_connection」が違っているのです。
      なるほど、INSERTで文字化けして、UPDATEで文字化けしないわけです。
      でも、どうしてこんな違いが生まれたのだろう?
      というか、なんで「character_set_database」が違うのか???

      MySQLのリファレンスマニュアル
      http://dev.mysql.com/doc/refman/5.1/ja/charset-connection.html
      の「SET CHARACTER SET」の説明の中に

      SET CHARACTER SET xステートメントは下記の3ステートメントと等価です。
      ----
      SET character_set_client = x;
      SET character_set_results = x;
      SET collation_connection = @@collation_database;
      ----
      collation_connectionを指定するとcharacter_set_connectionも照合順序に関係するキャラクタセットに指定されます(SET character_set_connection = @@character_set_databaseを実行することと同様)。
      とあるので、「SET CHARACTER SET」によって、「character_set_connection」が「character_set_database」と同じ値に設定されているようですが…
        ★日本公式フォーラム2009年9月1日本格始動!★
        http://modxcms-jp.com/bb/

        ▼ウェブ屋のCMS→modxヒキダス流(備忘録)
        http://d.hatena.ne.jp/hikidas_ikeda/
        ▼制作済みHTMLページをmodxで更新するデモ
        http://www.hikidas.com/hikidas/modx_document/modx_demo_osc2009kansai.php
        • 15497
        • 117 Posts
        さらに、UPDATEの際、「save_content.processor.php」のどこでMySQLの設定が変わるのか調べてみました。

        「save_content.processor.php」の407行目
        $was_published = $modx->db->getValue("SELECT published FROM $tblsc WHERE id='$id'");
        

        を通った後で、MySQLの設定が変わっています。
        つまり、DBAPI(manager/includes/extenders/dbapi.mysql.class.inc.php)の接続を使った(接続した?)後では、
        MySQLの設定が変わっています。
        ざっとソースを見た限りでは、「SET CHARACTER SET」も同じように設定しているように見えるのですが…
          ★日本公式フォーラム2009年9月1日本格始動!★
          http://modxcms-jp.com/bb/

          ▼ウェブ屋のCMS→modxヒキダス流(備忘録)
          http://d.hatena.ne.jp/hikidas_ikeda/
          ▼制作済みHTMLページをmodxで更新するデモ
          http://www.hikidas.com/hikidas/modx_document/modx_demo_osc2009kansai.php
          • 15497
          • 117 Posts
          とりあえず、私として導き出した結論は、

          PHPの「mysql_select_db」は、与えられたデータベース名がバッククォートで囲まれていると正しく動作しないらしい。
          ということです。
          PHPマニュアルには、残念ながらそのあたりは載ってませんね。
          http://jp.php.net/manual/ja/function.mysql-select-db.php

          MODxの中でも、mysql_select_dbを使う箇所では、
          たいていの箇所でバッククォートを削る処理を入れています。
          (ってことは、MODxでは、データベース名に「create」等のMySQL予約語は使えないってことですね)(※2)

          例えば、DBAPI(manager/includes/extenders/dbapi.mysql.class.inc.php)も、
          mysql_select_db直前の91行目で、バッククォートを削っています。
          $dbase = str_replace('`', '', $dbase); // remove the `` chars
          

          残念ながら、管理画面の「manager/index.php」等、何箇所か、これをやっていないところがあります。
          そのため、「character_set_database」が壊れて、文字化けの不具合が出ていると思われます。

          で、一番簡単な対処方法は「manager/includes/config.inc.php」の10行目あたりの
          $dbase = '`hogehoge`';
          

          の2つのバッククォート「`」を削って、
          $dbase = 'hogehoge';
          

          とすることですね。

          なお、この現象、および、対処法の対象となる環境は、(私のわかる範囲では)以下です。

          MODxの設定をutf8にしていて、MySQLサーバー側のデフォルトがutf8以外、さらに、
          MODx用のデータベースを「utf8」で設定(character_set_databaseをutf8に)している場合、
          多くの場合で、全角チルダ「~」や機種依存文字が「?」に化ける。
          (ドキュメント新規作成では化け、編集では化けない。チャンクは新規も編集も化ける。等)

          ちなみに、設定値を調べるには、phpMyAdminやコマンドラインから、
          MODx用のデータベースに対して、SQLで「SHOW VARIABLES LIKE ’character_set%’;」を実行します。

          あと、参考までに…

          対処方法として考えられる方法に、
          mysql_select_db直前で、バッククォートを削る以下の行を挿入する。
          $dbase = str_replace('`', '', $dbase); // remove the `` chars
          

          ということが考えられます。

          MODx0.9.6.1p2では、「mysql_select_db」を使っている箇所が15箇所あり、
          そのうち、上記の対応済みと思われるものが9箇所、
          以下の6箇所が未対応と思われます。(使われてなさそうなものも含む)
          --------
          manager/index.php(140):
          manager/includes/document.parser.class.inc.php(2480):
          manager/includes/veriword.php(79):
          manager/media/browser/mcpuk/connectors/php/config.php(49):
          manager/media/ImageEditor/config.inc.php(22):
          manager/processors/login.processor.php(23):
          --------
          ちなみに、以下の2箇所に関しては、現状では呼び出し側で対応しているようです。
          --------
          install/sqlParser.class.php(28):
          manager/actions/bkmanager.static.php(269):
          --------

          (※1)タイトル変えました。
          (※2)データベース名にMySQL予約語を使っても大丈夫そうです。
            ★日本公式フォーラム2009年9月1日本格始動!★
            http://modxcms-jp.com/bb/

            ▼ウェブ屋のCMS→modxヒキダス流(備忘録)
            http://d.hatena.ne.jp/hikidas_ikeda/
            ▼制作済みHTMLページをmodxで更新するデモ
            http://www.hikidas.com/hikidas/modx_document/modx_demo_osc2009kansai.php
            • 28073
            • 164 Posts
            そうしです。

            kazuikeさん、細かい検証ありがとうございます smiley
            う~ん、バッククォートのあるなしで動作が変わるのは困ったものですね。
            バグのような気もしますが、どうなんでしょう。

            気分的にはバッククォートをすぱっと取り除きたいところですが、バッククォートがないとデータベース名に"-(ハイフン)"が含まれている場合にエラーになっちゃうんですよね。
            でもMODx内部でバッククォートの取り扱いがまばらだったって事は"-(ハイフン)"付きのデータベースを使っていたら動かなかったって事か。。。
            ただ、データベース名に"-"入れる人ってあまりいないような気もしますが :’(

            ちなみに僕のときはサーバからクライアントまで全部UTF-8で統一したときはこの文字化けは発生せず、サーバ側のデフォルト文字コードがShift_JIS、作ったDBとクライアントの文字コードがUTF-8の時に文字化けが発生してました。

            あとちょっと関連してるかは不明ですが、kazuikeさんのMySQLのサーバ側デフォルト文字コードがEUC(ujis)だということなので。。。
            僕は以前UTF-8なMySQLにDBダンプデータをリストアした際にダンプデータの中に"character set ujis"が紛れ込んでいて、全角チルダ"~"が"?"になったりしたことがありました。
            そしてMacの「〜」(波ダッシュ)は文字化けしません。
            このときはダンプデータの中のcharacter set ujisを片っ端から消してリストアして事なきを得ましたが、文字化けのタイプとしてはkazuikeさんの方と似てる気がします。

            [参考]
            http://ayd.jp/p_blog/archive-200702/article-1171908362.html

              • 376
              • 17 Posts
              こんばんは~ smiley

              レンタルサーバー利用で、同じく「? ? ? ?」になる文字化けに悩んでいました。
              kazuikeさんのバッククォートを削る方法を試してみたら一気に解決しました。
              この方法すごい~感動しました。ありがとうございます。

              「mysql_select_db()」について、一応少し調べてみましたが、データベース名のバッククォートと文字化けに関する話題は
              ここ以外には見当たらないですねぇ…。かなり特殊な環境依存なのでしょうか?
              元々「str_replace()」でバッククォートを取る処理をしているということは、
              (ハイフン付きのDB名以外なら)configの中身でバッククォートを取っちゃっても大丈夫ですよね。(多分)

              ちなみに私の文字化けが起きた時の環境です。
              参考になるでしょうか。

              ■サーバ環境

              • php 4.4.4
              • mysql 4.1.20

              ■.htaccessに記述していた内容
              php_value default_charset UTF-8
              php_value mbstring.language Japanese
              php_value mbstring.internal_encoding UTF-8
              php_value mbstring.http_input auto
              php_value mbstring.http_output pass
              php_flag mbstring.encoding_translation On
              php_flag mbstring.func_overload 0
              php_flag magic_quotes_runtime Off

              どこかにあったMEGUさんの投稿を参考にしました。

              ■php.infoで確認した「mbstring」の項目
              [table]
              [tr][td]Directive[/td][td]Local Value[/td][td]Master Value[/td][/tr]
              [tr][td]mbstring.detect_order[/td][td]auto[/td][td]auto[/td][/tr]
              [tr][td]mbstring.encoding_translation[/td][td]On[/td][td]Off[/td][/tr]
              [tr][td]mbstring.func_overload[/td][td]0[/td][td]0[/td][/tr]
              [tr][td]mbstring.http_input[/td][td]auto[/td][td]pass[/td][/tr]
              [tr][td]mbstring.http_output[/td][td]pass[/td][td]pass[/td][/tr]
              [tr][td]mbstring.internal_encoding[/td][td]UTF-8[/td][td]EUC-JP[/td][/tr]
              [tr][td]mbstring.language[/td][td]Japanese[/td][td]Japanese[/td][/tr]
              [tr][td]mbstring.substitute_character[/td][td]no value[/td][td]no value[/td][/tr]
              [/table]

              ■MySQLの「サーバー変数と設定値」
              [table]
              [tr][td]変数[/td][td]セッション値[/td][td]グローバル値[/td][/tr]
              [tr][td]character set client[/td][td]utf8[/td][td]latin1[/td][/tr]
              [tr][td]character set connection[/td][td]utf8[/td][td]latin1[/td][/tr]
              [tr][td]character set database[/td][td]latin1[/td][td]latin1[/td][/tr]
              [tr][td]character set results[/td][td]utf8[/td][td]latin1[/td][/tr]
              [tr][td]character set server[/td][td]latin1[/td][td]latin1[/td][/tr]
              [tr][td]character set system[/td][td]utf8[/td][td]utf8[/td][/tr]
              [/table]

              ■MODxのファイルに加えた変更
              manager/includes/config.inc.phpに以下の記入。
              $database_connection_charset = 'utf8';


              ■文字化けした内容

              • MODx設定から「サイト名」に日本語を指定すると「? ? ? ?」(どんな文字でも)
              • チャンクなどリソースの「結果がありません」表示が「? ? ? ?」
              • ドキュメントを新規作成し、タイトルや内容に日本語を指定すると「? ? ? ?」(どんな文字でも)
              • 「? ? ? ?」になった部分は、phpMyAdminから見ても「? ? ? ?」

              ■文字化けしなかった内容

              • 既存ドキュメントに日本語を含めて編集し、上書きした場合

              ■文字化けが直った方法

              • kazuikeさん投稿の「config.inc.phpの「$dbase」にセットされている値のバッククォートを削除する方法」
              • soushiさん投稿の「SET CHARACTER SETが出てくる部分にSET NAMESを追加する方法」

              ちょっと違うのは、全角チルダなど特定の文字が化けるわけではなく、全部化けていた点です。
              少し前にSSMxさんが投稿されていた状態と同じです。
              あと、私のつたない英語力でtkfmさんが投稿されていたスレッドを読んでみると、
              「インストールの時点でSET NAMESかSET CHARACTER SETか選べるパッチ作った」みたいな内容(soushiさんの解決策)でしたが、
              0.9.6.2-rc2には、まだ採用されてなかったですね。文字化けも直らなかったのでバッククォートの問題も残ったままだと思います。

              長々とすみません。
              他の文字化けされている方に少しでも参考になれば幸いです。
                aco
                • 36592
                • 970 Posts
                Quote from: aco at Sep 02, 2008, 05:20 PM

                あと、私のつたない英語力でtkfmさんが投稿されていたスレッドを読んでみると、
                「インストールの時点でSET NAMESかSET CHARACTER SETか選べるパッチ作った」みたいな内容(soushiさんの解決策)でしたが、
                0.9.6.2-rc2には、まだ採用されてなかったですね。
                昨夜のSVN版のアップデート(rev.4014)で実装されました。
                http://svn.modxcms.com/crucible/changelog/modx/branches/0.9.6?cs=4014

                acoさんが書かれたとおり、既存の「SET CHARACTER SET」が実行されている箇所について、
                「SET NAMES」とどちらを使うかコンフィグで設定できるようになったはずです。

                個人的には、本当にこれだけの箇所だけで良いのか?(他にもこれを入れるべき箇所があるのではないか?)
                という点が気になっています...
                  • 15497
                  • 117 Posts

                  気分的にはバッククォートをすぱっと取り除きたいところですが、バッククォートがないとデータベース名に"-(ハイフン)"が含まれている場合にエラーになっちゃうんですよね。
                  PHP 5.1.6
                  MySQL 5.0.22
                  でテストした限りでは、
                  「mysql_select_db」にハイフン付きのデータベース名を渡してもちゃんと機能しました。
                  ということで、
                  元々、mysql_select_dbは、正味(バッククォート無し)のデータベース名を渡すような仕様で作られているのではないかとも思ったりします。
                  (じゃ、バッククォート付きでもデータベースの選択ができるのは、おまけ機能かな?)

                  ただ、
                  MODxでも、SQLの中で、テーブル名の指定に「<データベース名>.<テーブル名>」としているものがかなり多いので、こういう箇所は、データベース名にハイフン等が入っていると問題ありそうですね。

                  ところで、
                  最近は、テーブル名の指定にデータベース名を付けることが、一般的、もしくは、推奨の使い方なのでしょうか?
                  (私は古い人間なので…、時代が変わったのかな?)
                    ★日本公式フォーラム2009年9月1日本格始動!★
                    http://modxcms-jp.com/bb/

                    ▼ウェブ屋のCMS→modxヒキダス流(備忘録)
                    http://d.hatena.ne.jp/hikidas_ikeda/
                    ▼制作済みHTMLページをmodxで更新するデモ
                    http://www.hikidas.com/hikidas/modx_document/modx_demo_osc2009kansai.php
                    • 15497
                    • 117 Posts
                    SQLの中で、テーブル名の指定に「<データベース名>.<テーブル名>」としているのであれば
                    $dbase = str_replace('`', '', $dbase); // remove the `` chars
                    

                    は、元のデータベース名「$dbase」自体を書き換えているので、危険ですね。
                    mysql_select_db(str_replace("`", "", $dbase))
                    

                    もしくは、
                    mysql_select_db(trim($dbase, '`'))
                    

                    のように、mysql_select_dbに渡すものだけバッククォートを削るべきなんでしょうね。
                      ★日本公式フォーラム2009年9月1日本格始動!★
                      http://modxcms-jp.com/bb/

                      ▼ウェブ屋のCMS→modxヒキダス流(備忘録)
                      http://d.hatena.ne.jp/hikidas_ikeda/
                      ▼制作済みHTMLページをmodxで更新するデモ
                      http://www.hikidas.com/hikidas/modx_document/modx_demo_osc2009kansai.php
                      • 36592
                      • 970 Posts
                      Quote from: tkfm at Sep 03, 2008, 12:45 AM

                      昨夜のSVN版のアップデート(rev.4014)で実装されました。
                      早速アップデートしてみましたが... やはりというか、やっぱり全部文字化けに... :’(
                      既存の日本語データ(DB上は正しく格納されたもの)はFrontendで全て「? ? ? ?」に。
                      アップデート後新規で追加した日本語データ(DB上は文字化け)はFrontendで正常に表示されます。

                      「SET NAMES」にしても「SET CHARACTER SET」にしてもどちらも結果は同じ。
                      しかも、本来問題となるはずの無い全ての文字コードがUTF-8で統一された環境なのに...

                      あ~あ、恐れていたことがやはり起こった。
                      どなたか他にも試して頂ける方いらっしゃいませんか?