myx_backupモジュールphp7への対応

このトピックの投稿一覧へ

なし myx_backupモジュールphp7への対応

msg# 1.1
depth:
1
前の投稿 - 次の投稿 | 親投稿 - 子投稿なし | 投稿日時 2022/9/14 11:44 | 最終変更
タツ  管理人   投稿数: 2255
Xoops Cube Legacyサイト構築の際、重要な部分の1つにデータベースのエクスポートとインポートがあります。これにはサーバーのPhpMyAdminを利用するのも1つの方法ですが複数あったほうが安心なのは言うまでもありません。というのもPhpMyAdminは時間が掛かったり、エラーが発生したりと利用できなくなることがあったからです。BigDumpというソフトがとても便利でしたが、残念ながら今の所php7では動作しません。

従って、このモジュールはデータベースを扱う上で必要なモジュールだと考えています。そのままではphp7では動作しないので編集してみました。なお、この方法での細かなミスがあったので2022/09/16に再度編集し、ローカル環境(サーバーxampp7.4.25、legacy-2.3を起用)での動作を再確認したものです。

参考サイト
MySQL関数からMySQLi関数への移行作業メモ
myx_backup Ver 1.10のPHP7対応
myx_backupダウンロード

■1.PHP7で利用できない関数のコメントアウト
set_magic_quotes_runtime→PHP7で削除されました。
get_magic_quotes_runtime→php7では非推奨
これらが含まれているコード行はコメントアウトし削除修正しましたが問題なく動作するようです。

変更対象ファイルは
modules/myx_backup/admin/backup_bymod.php
modules/myx_backup/admin/backup.php
modules/myx_backup/admin/dump.php
modules/myx_backup/admin/restore.php

ファイル内の以下のコード行をコメントアウトします
$mqr = get_magic_quotes_runtime();
set_magic_quotes_runtime(0);
set_magic_quotes_runtime($mqr);
↓コメントアウト
//$mqr = get_magic_quotes_runtime();
//set_magic_quotes_runtime(0);
//set_magic_quotes_runtime($mqr);

■2.PHP7での配列書式変更
変更対象ファイル
array()は殆どのファイルにて多数存在するので省略します
$name = array() 
変更↓
$name = [];

■3.mysqlfetchfield_change.phpの追加
mysql_fetch_fieldのphp5からphp7への互換性を維持するためmodules/myx_backup/admin/mysqlfetchfield_change.phpを追加しました。
このファイルの追加対象ファイルは
modules/myx_backup/admin/function.php
modules/myx_backup/admin/export.php

mysqlfetchfield_change.phpコード内容
<?php
/**
 * MySQL関数からMySQLi関数への移行作業メモ(https://qiita.com/from_kyushu/items/0023a2b0816f82e1740f)より引用
 * php7のmysqli_fetch_field_direct() を mysql_fetch_field() の代替とするための処理プログラム
 * mysql_fetch_field() は型情報を文字列として持っているが mysqli_fetch_field_direct() はビット情報を整数として持っている
 *
 * MYSQLI_*_FLAG定数を読み込みビットフラグ整数と名称の配列を生成する。
 * 引数に true を渡すと旧MySQL関数互換の配列を返す。
 *
 * @param bool MySQL関数互換フラグ
 * @return array
 */
function get_flag_names($compat = false){
	if($compat){
	  return [
		1 => "not_null",
		2 => "primary_key",
		4 => "unique_key",
		8 => "multiple_key",
		16 => "blob",
		32 => "unsigned",
		64 => "zerofill",
		128 => "binary",
		256 => "blob",
		512 => "auto_increment",
		1024 => "timestamp"
	  ];
	} else {
	  $flags = [];
	  $constants = get_defined_constants(true);
	  foreach ($constants['mysqli'] as $c => $n){
		if (preg_match('/MYSQLI_(.*)_FLAG$/', $c, $m)){
		  if (!array_key_exists($n, $flags)){
			$flags[$n] = strtolower($m[1]);
		  }
		}
	  }
	  return $flags;
	}
  }
  
  /**
   * MYSQLI_TYPE_*定数を読み込みビットフラグ整数と名称の配列を生成する。
   * 引数に true を渡すと旧MySQL関数互換の配列を返す。
   *
   * @param bool MySQL関数互換フラグ
   * @return array
   */
  function get_type_names($compat = false){
	$types = [];
	$constants = get_defined_constants(true);
	foreach ($constants['mysqli'] as $c => $n){
	  if (preg_match('/MYSQLI_TYPE_(.*)$/', $c, $m)){
		$types[$n] = strtolower($m[1]);
	  }
	}
	// MySQL関数互換モードの場合、MySQL関数が返す値で置き換える
	if($compat){
	  $types[0] = "real";
	  $types[1] = "char";
	  $types[2] = "int";
	  $types[3] = "int";
	  $types[4] = "real";
	  $types[5] = "real";
	  $types[8] = "int";
	  $types[9] = "int";
	  $types[248] = "string";
	  $types[249] = "blob";
	  $types[250] = "blob";
	  $types[251] = "blob";
	  $types[253] = "string";
	}
	return $types;
  }
  
  /**
   * mysqli_fetch_field()等で取得したstdClassオブジェクトをmysql_fetch_field()互換の形式で作り直す。
   *
   * @param object mysqli_fetch_field()等で取得したstdClassオブジェクト
   * @param bool MySQL関数互換フラグ
   * @return object
   */
  function remake_field_object($field, $compat = true){
	$obj = new stdClass();
	$flags = get_flag_names($compat);
	$types = get_type_names($compat);
	$numeric_types = [1, 2, 3, 4, 5, 8, 9, 16, 246];
	$compat_flags  = ["not_null", "primary_key", "unique_key", "multiple_key", "blob", "unsigned", "zerofill"];
	$nocompat_keys = ["orgname", "orgtable", "db", "catalog", "length", "charsetnr", "decimals"];
	$compat_sortkey = ["name", "table", "def", "max_length", "not_null", "primary_key", "multiple_key", "unique_key", "numeric", "blob", "type", "unsigned", "zerofill"];
	foreach((array) $field as $key => $value){
	  switch($key){
	  case "flags":
		foreach($flags as $num => $name){
		  // MySQL関数互換モードの場合、mysql_fetch_field() の返り値にないプロパティは飛ばす
		  if($compat == true && ! in_array($name, $compat_flags)) continue;
		  $obj->$name = ($value & $num) ? 1 : 0;
		}
		break;
	  case "type":
		$obj->type = $types[$value];
		// $obj->numericはflagsの中には含まれていないため、typeを見て判断する
		$obj->numeric = (in_array($value, $numeric_types)) ? 1 : 0;
		// TEXT型の場合、typeはblobとなるがflagsではblobとして扱われないためここでフラグを立てる
		if($obj->type == "blob") $obj->blob = 1;
		break;
	  default:
		// MySQL関数互換モードの場合、mysql_fetch_field() の返り値にないプロパティは飛ばす
		if($compat == true && in_array($key, $nocompat_keys)) break;//php7.4に合わせcontinue;→break;に変更
		$obj->$key = $value;
		break;
	  }
	}
	// オブジェクトを配列にキャストして処理する場合、キャスト後の配列の順序はプロパティ定義順となる。
	// そのため、MySQL関数互換モードの場合MySQL関数と同一の定義順に並び替える。
	if($compat == true){
	  $sorted = new stdClass();
	  foreach($compat_sortkey as $key){
		$sorted->$key = $obj->$key;
	  }
	  $obj = $sorted;
	}
	return $obj;
  }
  
?>

■4.mysqlからmysqliへの関数コード変更
mysqliコードへの変更対象ファイルは
modules/myx_backup/admin/function.php
modules/myx_backup/admin/export.php
です。
変更内容は
mysql_num_fields();
mysql_field_name();
mysql_fetch_field();
mysql_field_flags();
それぞれ変更↓
mysqli_num_fields(); //変更
mysqli_fetch_field_direct() ->name;//変更
remake_field_object(); //変更
mysqli_fetch_field_direct() ->flags;//変更

■5.テーブル名を比較する際に{prefix}{dirname}がそのまま表示される件の対処
なぜかテーブル名が{prefix}{dirname}がそのまま表示され、うまく取得できないままテーブル名を比較し違うものと判断されています。str_replace関数を使って{prefix}は削除、{dirname}はモジュール名に変換することにしました。プロのプログラマーであれば他の方法があるかもしれません。
変更対象ファイルは
modules/myx_backup/admin/function.php
modules/myx_backup/admin/backup_bymod.php

■6.zipのダウンロードが破損されているとのエラーメッセージが出る件
html/class/class.zipfile.phpの編集が必要です。
eval('$hexdtime = \'' . $hexdtime . '\';'); 
変更→eval('$hexdtime = "' . $hexdtime . '";');

-----------------------

次に上記を元にして実際のコード変更を編集します
modules/myx_backup/admin/function.phpの編集
4行目に追加
<?php
if (!defined('XOOPS_ROOT_PATH')) { exit(); }
if (!defined('MYXBU_SQLComment')) { exit(); }
require_once './mysqlfetchfield_change.php';//追加

・mysqlからmysqliへの関数コード変更26行目あたり
for ($i = 0; $i < mysqli_num_fields($res3); $i++) { //変更
		$fname = mysqli_fetch_field_direct($res3, $i) ->name; //変更
		$fmeta[$fname] = remake_field_object($res3, $i);//変更
		$fflag[$fname] = mysqli_fetch_field_direct($res3, $i) ->flags; //変更

・正しいテーブル名の取得112行目辺り
if (isset($modversion['tables'])) {
	foreach ($modversion['tables'] as $table) {
		if ($table != '') {
			$before_table_name = ['{prefix}_', '{dirname}']; //追加
			$after_table_name   = ['', $dname];//追加
			$table2  = str_replace($before_table_name, $after_table_name, $table);//追加
			$ModuleTables[$xoopsDB->prefix($table2)] = htmlspecialchars($dname);//変更
			$ModuleByDir[$xoopsDB->prefix($table2)] = false;//変更
		}
	}
}


modules/myx_backup/admin/export.phpの編集
4行目に追加
<?php
require_once '../../../include/cp_header.php';
require_once './header.php';
require_once './mysqlfetchfield_change.php';//追加。

21行目辺りから
if ($op == 'export') {
	//	Export Main
	$result = '';
	$res = $xoopsDB->query("SELECT * FROM `$table_name` LIMIT 0");
	$fnum = mysqli_num_fields($res); //変更
	$comma = '';

	for ($i = 0; $i < $fnum; $i++) {
		$fname[$i] = mysqli_fetch_field_direct($res, $i) ->name;  //変更
		$fmeta[$i] = remake_field_object($res, $i); 		  //変更
		$fflag[$i] = mysqli_fetch_field_direct($res, $i) ->flags; //変更
		$result .= $comma.'"'.str_replace('"', '""', $fname[$i]).'"';
		$comma = ', ';

	}


modules/myx_backup/admin/backup_bymod.phpの編集
・不要関数のコメントアウト
//$mqr = get_magic_quotes_runtime(); 68行目
//set_magic_quotes_runtime(0);69行目
//set_magic_quotes_runtime($mqr);81行目

・正しいテーブル名の取得41行目あたり
foreach ($table2module as $tbl => $mod) {
	if ($mod_name == $mod) {
		$before_mod_name = ['_{prefix}', '{dirname}']; //追加
		$after_mod_name   = ['', $mod_name];//追加
		$tbl_change  = str_replace($before_mod_name, $after_mod_name, $tbl);//追加
		$my_tables[$tables_count++] = $tbl_change;//変更
	}
}

modules/myx_backup/admin/backup.phpの編集
・不要関数のコメントアウト
//$mqr = get_magic_quotes_runtime(); 33行目
//set_magic_quotes_runtime(0);34行目
//set_magic_quotes_runtime($mqr);53行目


modules/myx_backup/admin/dump.phpの編集
・不要関数のコメントアウト
//$mqr = get_magic_quotes_runtime(); 36行目
//set_magic_quotes_runtime(0);37行目
//set_magic_quotes_runtime($mqr);58行目

modules/myx_backup/admin/restore.phpの編集
・不要関数のコメントアウト
//$mqr = get_magic_quotes_runtime(); 49行目
//set_magic_quotes_runtime(0);50行目
//set_magic_quotes_runtime($mqr);118行目


html/class/class.zipfileの編集
・圧縮エラー回避93行目
eval('$hexdtime = \'' . $hexdtime . '\';');
変更↓	
eval('$hexdtime = "' . $hexdtime . '";');//変更

以上の編集で今の所正常に機能しているようです。
但し、最適化については時間が掛かりステータスに「note -- Table does not support optimize, doing recreate + analyze instead」と表示されています。この部分の解消方法についてはよくわかりません。
投票数:4 平均点:5.00

投稿ツリー

  条件検索へ


旅と気ままなフォーラム新着投稿

旅と気ままなフォーラムメニュー

欲しい商品が必ず見つかるメジャーなネットショップ

このサイト内の検索

オンライン状況

19 人のユーザが現在オンラインです。 (2 人のユーザが 旅と気ままなフォーラム を参照しています。)

登録ユーザ: 0
ゲスト: 19

もっと...

Facebook,RSSリンク表示


RSSicon 最新記事のRSS