Nacky - Snowland.net

Nacky(Issei Ishii)がDJ/Composerのようなふりして書き散らすblogサイト

Info

Nacky - Snowland.net - blogを移転しました

2011-04-06

Nucleusのアップグレードと文字化け解消

恥ずかしながら本blogのシステムであるNucleusのアップグレードをさぼっておりました.
しかしまぁセキュリティ的なアレやコレやあるみたいなのでアップグレードを行いました.

手順は
・upgradesのスクリプトを実行してDB内容を更新
・overwritesを上書きして完了

簡単.

しかし見てみるとblog記事が盛大に文字化けしてる.
ということで原因調査.

通常は大丈夫だがphpMyAdminで文字化け [Archive] - XREA&CORE SUPPORT BOARD

こちらの症状が当てはまります.
原因は昔に作ったMySQLのDBが文字コードlatin1だったため.
DBのエンコーディングがlatin1だと,中身がUTF-8でもSET NAMES utf-8;して扱うと文字化けします.

正しい状態では,DBもutf8指定,中身もUTF-8の文字列となっているはず.

しかし上記の記事にも「ただ、既に作成済みのデータについてはまた一から作り直すしかないかと思っているのですが・・・」とあります.
私も知る限りサクっとlatin1内のUTF-8文字列をutf8に持ってくる方法は知りません.

…じゃぁ自力でやるか.

そんなわけでPHPを書いて移行作業開始.


・phpMyAdminで構造だけエクスポート(一応auto_increment値も含めておいた)
・エクスポートしたSQLのうち,テーブル接頭辞部分を置換する
(hoge_nucleus_item みたいに hoge_ を接頭辞にしてたらそこを fuga_ に変更)
・変更したSQLをDB上で実行
 fuga_nucleus_item のように構造だけ作られる

・旧tableからlatin1で読み出してきて新tableにutf8で書き込むスクリプトを実行
こんな感じ(セキュリティ的な配慮がないので.htaccessなりで確保して実行)

<?php
$dbhost = 'localhost';
$dbuser = 'dbuser';
$dbpass = 'dbpass';
$dbname = 'dbname';
$oldprefix = 'hoge_';
$newprefix = 'fuga_';

// set max_execution_time unlimited
set_time_limit(0);

$CONN=mysql_connect($dbhost,$dbuser,$dbpass);
if(!$CONN) exit;
if(!mysql_query("SET NAMES latin1;")) exit;
if(!mysql_query("USE ".$dbname.";")) exit;

$sql="SHOW TABLES LIKE '".$oldprefix."nucleus_%';";
$rs=mysql_query($sql);
if(!$rs) exit;
$tnames=array();
while($ra=mysql_fetch_array($rs)){
  $tnames[]=$ra[0];
}

$tables=array();
foreach($tnames as $t){
  $sql="DESCRIBE ".$t.";";
  $rs=mysql_query($sql);
  if(!$rs) exit;
  $tables[$t]=array();
  while($ra=mysql_fetch_array($rs)){
    $tables[$t][]=$ra['Field'];
  }
}

// read from old tables
$i=0;
foreach($tables as $tname=>$cols){
  $j=0;
  echo "table(".$i."): ".$tname;
  if(!mysql_query("SET NAMES latin1;")) exit;
  $sql="SELECT * FROM ".$tname.";";
  $rs=mysql_query($sql);
  if(!$rs){
    echo mysql_error();
    exit;
  }
  if(mysql_num_rows($rs)==0) continue;
  if(!mysql_query("SET NAMES utf8;")) exit;
  while($ra=mysql_fetch_array($rs)){
    $vals=array();
    foreach($cols as $c){
      $vals[]="'".mysql_real_escape_string($ra[$c])."'";
    }
    $sql="INSERT INTO "
      .str_replace($old_prefix,$new_prefix,$tname)
      ." ( "
      .implode(',',$cols)
      .") VALUES ("
      .implode(',',$vals)
      .");";
    if(!mysql_query($sql)){
      echo mysql_error();
      exit;
    }
    $j++;
  }
  echo " : ".$j." rows.\n";
  $i++;
  flush();
}
echo 'complete!';


・config.phpの接頭辞を変更
・再度アップグレード作業

以上で無事に正しい(?)UTF-8環境になりました.

ちなみに今回のアップグレードはNucleus CMS 3.4(だったか?)から3.64への作業でした.
posted at 22:26:07 on 2011-04-06 by nacky - Category: Com/Tech ( PHP , Database )

ソニーストア

TrackBack

このエントリにトラックバックはありません
トラックバックURL

Comments

No comments yet