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系以降でないと動かないかと思います(未確認)。

<?php
define('URL_FROM', '@https?://test\.examples\.com/@');
define('URL_TO', 'http://stg.examples.com');

define('PATH_FROM', '@/var/www/test.examples.com/htdocs@');
define('PATH_TO',  '/var/www/stg.examples.com/htdocs');

define('DB_NAME', 'examples_db');
define('DB_USER', 'examples_user');
define('DB_PW', 'abababa');

function array_obj_walk_recursive(&$arr, $callback) {
    foreach ($arr as $key => &$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);
}

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

フォローする