WordPressのドメイン等変更手順

WordPressのドメインを変更する方法について。例えば、「開発サーバで作成したコンテンツをステージングサーバに移す」なんて場合を想定しています。

単純に

1. DocumentRoot 以下のファイルを丸ごとコピー
2. 開発サーバのDBの中身をmysqldump
3. mysqldump の中身をエディタで編集して、開発サーバのURLとインストールパス(DocumentRoot)をステージングサーバのものに変更
4. ステージングサーバのDBにリストア

で良さそうな気がするのですが、これをやると wp_postmeta テーブルや wp_optionsテーブルの中のserializeされた値がことごとく壊れます… なぜなら、serializeされたデータは

s:19:”http://examples.com”

のように、文字列の大きさを含んでいるからですね。これを単純に http://examples.com から http://examples.jp に変えたら、

s:18:”http://examples.jp”

となるべきものが

s:19:”http://examples.jp”

となるわけですから、正しく認識されなくなるわけです。

## serializeされた文字列をどう変換するか

* エディタで編集しながらいちいち文字列数えるのは面倒
* かと言って、mysqldumpしたものをPHPでパースする元気もない

というわけで、

* 一旦DBにリストアしたものを、PHPから読み出して変更

が一番速かろうということで、こんなコードを書いてみました。

変換の対象としているのは、wp_posts, wp_postmeta, wp_optionsテーブルだけです。プラグイン等が作るテーブルは無視してます。もうちょっと頑張れば、全テーブルの全カラムを変換出来ると思うのですが、目的を達成したらめんどくさくなっちゃったってことで(^^;;

注意点として、DB_NAMEとDB_USERとDB_PWが **移行先** のものであることを確認して使ってください。移行元を指定してしまうと、せっかく作った開発サーバの中身が壊れますのでw あと、動作確認した PHP のバージョンは 5.4.27 です。多分 5.3系以降でないと動かないかと思います(未確認)。

&$val) {
if (is_array($val) || is_object($val)) {
array_obj_walk_recursive($val, $callback);
}
else {
$callback($val, $key);
}
}
}

function replace_url_path(&$value) {
$value = preg_replace(URL_FROM, URL_TO, $value);
$value = preg_replace(PATH_FROM, PATH_TO, $value);
}

function replace_serialized_table($db, $tbl_name, $col_name, $pkey) {
$stmt = $db->query(“SELECT * from $tbl_name”);

while ($data = $stmt->fetch(PDO::FETCH_ASSOC)) {
$value = $data[$col_name];

if (($value_uns = @unserialize($value)) !== FALSE) { // 中身がserializeされているか判定
if (is_string($value_uns)) {
replace_url_path($value_uns);
}

if (is_array($value_uns) || is_object($value_uns)) {
array_obj_walk_recursive($value_uns, “replace_url_path”);
}

$value = serialize($value_uns);
}
else {
replace_url_path($value);
}

unset($value_uns);

$stmt2 = $db->prepare(“UPDATE $tbl_name SET $col_name = :val WHERE $pkey = :id”);
$stmt2->bindValue(‘:val’, $value);
$stmt2->bindValue(‘:id’, $data[$pkey]);
$stmt2->execute();
unset($value, $stmt2);
}
unset($data, $stmt);
}

/*** MAIN ***/
try {
$db = new PDO(“mysql:host=localhost; dbname=” . DB_NAME, DB_USER, DB_PW,
array(
PDO::MYSQL_ATTR_INIT_COMMAND => “SET CHARACTER SET `utf8`”
));
$db->query(“SET NAMES utf8;”);
}
catch (PDOException $e) {
var_dump($e->getMessage());
exit(1);
}

try {
$db->beginTransaction();

/** wp_posts の処理 **/
$stmt = $db->query(‘SELECT * from wp_posts’);
while ($data = $stmt->fetch(PDO::FETCH_ASSOC)) {
$content = $data[‘post_content’];
replace_url_path($content);

$guid = $data[‘guid’];
replace_url_path($guid);

$stmt2 = $db->prepare(‘UPDATE wp_posts SET post_content = :content, guid = :guid WHERE ID = :id’);
$stmt2->bindValue(‘:content’, $content);
$stmt2->bindValue(‘:guid’, $guid);
$stmt2->bindValue(‘:id’, $data[‘ID’]);
$stmt2->execute();
unset($content, $stmt2);
}
unset($data, $stmt);

/** wp_postmeta の処理 **/
replace_serialized_table($db, ‘wp_postmeta’, ‘meta_value’, ‘meta_id’);

/** wp_options の処理 **/
replace_serialized_table($db, ‘wp_options’, ‘option_value’, ‘option_id’);

$db->commit();
}
catch (PDOException $e) {
var_dump($e->getMessage());
$db->rollBack();
exit(1);
}

?>

スポンサーリンク
スポンサーリンク:

フォローする