Nucleus(JP)フォーラム

NucleusCMS日本語版ユーザーのためのサポートフォーラムです。疑問が生じたらまずは記事検索をご利用ください。

ログインしていません。

#1 2011-01-17 16:12:39

kotorisan
メンバー
登録日: 2007-01-17
投稿: 49

Re: dbのcharset提案

質問ではないのですが

先ほどutf8に完全移行したので どうでもいいのですが、
EUC-JPで使っている方がまだいると思うので 少し修正の提案です。

(1)
EUC-jp環境で使用していた場合、
さくらなどのサーバーでは、
データベースを1個しか所有できないため
データベースとテーブルの文字コードが違う場合があります。

私がそうですけど
データベース自体はUTF8に設定していてテーブルの文字コードEUC-JPで違う場合があります。

コアのmysql.phpでは、データベースの文字コードで設定しているので
テーブルの文字コードを参照するか、直接書き換えるように注意書きしたほうがいいように思います。

        $charset  = $fetchDat['Value'];
//        $charset  = "ujis"; // 必要な方は、コメントをはずしてください

↑みたいな感じで


それと、
(2)使用する言語とデータベースの文字コードが一致していないと文字化けする件も
   修正がいるような気がします。

globalfunctions.php

// check if valid charset
if (!encoding_check(false, false, _CHARSET)) {
    foreach(array($_GET, $_POST) as $input) {
        array_walk($input, 'encoding_check');
    }
}
の下あたりで

 if (defined('_CHARSET'))
 {
   if ( (strtolower(strval($MYSQL_HANDLER[0])) == 'mysql')
      ||
        (strtolower(strval($MYSQL_HANDLER[1])) == 'mysql') )
   {  // mysql
      $local_charset = strtolower(_CHARSET);
      switch ($local_charset)
      {
         case 'utf-8':
           $local_charset  = "utf8";
           break;
         case 'euc-jp':
           $local_charset  = "ujis";
           break;
        }
/*
      $server_charsets = array();

      $tmp_res = @sql_query('SHOW CHARACTER SET');
      while ($tmp_row = @sql_fetch_row($tmp_res))
         $server_charsets[] = strtolower($tmp_row[0]);
      unset($tmp_res,$tmp_row);

      if (in_array($local_charset , $server_charsets))
         sql_query(sprintf('SET CHARACTER SET %s', $local_charset));
*/
      if (in_array($local_charset , array("utf8","ujis"))) 
         sql_query(sprintf('SET CHARACTER SET %s', $local_charset));
   } // else // other database
 }

管理画面のタイトルが変になるので、もう少し他の方法がいいかもしれません。

オフライン

#2 2011-01-17 23:52:07

Mocchi
メンバー
登録日: 2006-11-19
投稿: 438

Re: dbのcharset提案

これ、私もとても気になっていた話題です。

ここらへんの私の理解はnucleus-jp-developersの2010年12月25日のメッセージで書いてあります。

基本、MySQLが持つ文字コード設定は照合順序に関するもので、MySQLと入出力を行うスクリプト側で入力も出力も同じ文字コードで処理しているのであれば、問題ないんじゃないかという理解です。

なので、文字化けの原因は、スクリプトからデータベースへの入力、あるいはデータベースからの出力をスクリプトで処理する際に起こっていて、つまりはスクリプトの問題かなぁと考えています。

考え違いであればご指摘下さい。

オフライン

#3 2011-01-18 13:17:00

kotorisan
メンバー
登録日: 2007-01-17
投稿: 49

Re: dbのcharset提案

Mocchi さんの発言:

これ、私もとても気になっていた話題です。

ここらへんの私の理解はnucleus-jp-developersの2010年12月25日のメッセージで書いてあります。

基本、MySQLが持つ文字コード設定は照合順序に関するもので、MySQLと入出力を行うスクリプト側で入力も出力も同じ文字コードで処理しているのであれば、問題ないんじゃないかという理解です。

なので、文字化けの原因は、スクリプトからデータベースへの入力、あるいはデータベースからの出力をスクリプトで処理する際に起こっていて、つまりはスクリプトの問題かなぁと考えています。

考え違いであればご指摘下さい。

はい、スクリプトの問題です

データベースの照合順序とスクリプト側で処理する文字コードが一致している場合は問題はおきません。

問題点は、メンバーの設定に「使用する言語」の設定があることです。
それさえなければ 特に問題は無いと思います。

照合順序がサーバーとクライアントで違う場合は、Mysql側で内部で自動文字コード変換が働くので
それを利用すると、簡単に解決するので、メンバーの設定に「使用する言語」の設定にあわせて
データベースの照合順序をかえるということです。
そうでない場合は、スクリプト全体をバッファリングして出力時に文字コードを一括変換するなどの修正が必要になってきます。

utf8に移行する際に必要な場合は、下のスクリプトで照合順序を変更できます。
壊れるといけないので、使う前に、念のためバックアップしてください。

<?php
  // nucleusテーブルの照合順序を utf8に変換します。
  // ujis_japanese_ciになっている場合、一括変換したいときに使用します。

  $db_host = '127.0.0.1';
  $db_name = 'nucleus';
  $user = 'test';
  $password = '';
  $dsn = sprintf('mysql:dbname=%s;host=%s', $db_name, $db_host);

try {
   $dbh = new PDO($dsn, $user, $password);
   $stmt = $dbh->prepare("SHOW TABLES LIKE 'nucleus%'");
   $stmt->execute();
   $items = $stmt->fetchAll();

//  var_dump($items);
   foreach($items as $item)
   {
//   ALTER TABLE CONVERT TO CHARACTER SET charset_name [COLLATE collation_name]
//   $sql = sprintf('ALTER TABLE `%s` CONVERT TO CHARACTER SET UTF8', $item[0]);
     $sql = sprintf('ALTER TABLE `%s` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci', $item[0]);
     echo $sql."\n";
     $dbh->exec( $sql );
   }
} catch (PDOException $e) {
    echo 'Connection failed: ' . $e->getMessage();
}

?>

オフライン

#4 2011-01-20 10:17:10

きゃしゃ
メンバー
From: 北河内
登録日: 2007-12-15
投稿: 351

Re: dbのcharset提案

kotorisan さんの発言:

問題点は、メンバーの設定に「使用する言語」の設定があることです。
それさえなければ 特に問題は無いと思います。

あぁ、そうですよねー。DBの文字コードに関係なくいろんな文字コードが入出力される可能性があると考えるべきなんですよねー、設計思想的には。

となると、CHARSET確定した後、すなわち// check if valid charset の下あたりに接続キャラセット指定を移動することになりますね。

kotorisan(敬称略)の提案くださったコード、すごく丁寧なんですが、少々簡略化してこんなんでどうでしょうか。

// <add for garble measure>
if (in_array('mysql',$MYSQL_HANDLER)) {
	switch(strtolower(_CHARSET)){
		case 'utf-8':
			$charset = 'utf8';
			break;
		case 'euc-jp':
			$charset = 'ujis';
			break;
		case 'gb2312':
			$charset = 'gb2312';
			break;
		case 'shift_jis':
			// Note that shift_jis is only supported for output.
			// Using shift_jis in DB is prohibited.
			$charset = 'sjis';
			break;
		default:
			// iso-8859-x,windows-125x
			$resource = sql_query("show variables LIKE 'character_set_database'");
			$fetchDat = sql_fetch_assoc($resource);
			$charset  = $fetchDat['Value'];
			break;
	}
	$mySqlVer = implode('.', array_map('intval', explode('.', sql_get_server_info($MYSQL_CONN))));
	if ($mySqlVer >= '5.0.7' && function_exists('mysql_set_charset')) {
		mysql_set_charset($charset);
	} elseif ($mySqlVer >= '4.1.0') {
		sql_query("SET CHARACTER SET " . $charset);
	}
}
// </add for garble measure>*/

オフライン

#5 2011-03-22 23:44:45

Mocchi
メンバー
登録日: 2006-11-19
投稿: 438

Re: dbのcharset提案

Mocchiです。

3.62のPDOハンドラエラーと合わせて、文字化け対策のコードを日本語版の開発ソースにコミットしました。リビジョン1181です。

http://sourceforge.jp/projects/nucleus- ... ision=1181

可能な限りの文字化け対策ができたと思います。きゃしゃさん、kotorisan、お疲れ様でした。

オフライン

Board footer