[WordPress] WordPress のDB上のサイトURLを一気に変換

開発環境から本番環境に移行する時、サイトURLを変換したい時に使おう。

使い方

$ php replace-siteurl.php {new_site_url} /path/to/wordpress/



This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


#!/usr/bin/php
<?php
switch($argc) {
case 1:
case 2:
echo "please input new site url and wp directory name!\n";
exit();
default:
$old_site = isset($argv[3]) ? $argv[3] : '';
$path = $argv[2];
$new_site = $argv[1];
}
if ( !file_exists($path.'wp-load.php') && file_exists($path.'wp-config.php') ) {
echo "Not found wp-config.php!\n";
exit();
}
require_once(file_exists($path.'wp-load.php') ? $path.'wp-load.php' : $path.'wp-config.php');
global $wpdb;
$replace = new ReplaceSiteURL($new_site, $path, $old_site);
// wp_options
echo "{$wpdb->options} : replace '{$replace->old_site}' to '{$replace->new_site}' …\n";
printf("Result: %d\n\n", $replace->options());
// wp_posts
echo "{$wpdb->posts} : replace '{$replace->old_site}' to '{$replace->new_site}' …\n";
printf("Result: %d\n\n", $replace->posts());
// wp_postmeta
echo "{$wpdb->postmeta} : replace '{$replace->old_site}' to '{$replace->new_site}' …\n";
printf("Result: %d\n\n", $replace->postmeta());
// wp_usermeta
echo "{$wpdb->usermeta} : replace '{$replace->old_site}' to '{$replace->new_site}' …\n";
printf("Result: %d\n\n", $replace->usermeta());
// wp_commentmeta
echo "{$wpdb->commentmeta} : replace '{$replace->old_site}' to '{$replace->new_site}' …\n";
printf("Result: %d\n\n", $replace->commentmeta());
// replace class
class ReplaceSiteURL {
public $new_site;
public $old_site;
public $wp_path;
function __construct($new_site, $path, $old_site = '') {
$this->new_site = untrailingslashit(preg_match('/^https?:\/\//i', $new_site) ? $new_site : 'http://&#39;.$new_site );
$old_site = (!empty($old_site) && !preg_match('/^https?:\/\//i', $old_site) ? 'http://&#39;.$old_site : $old_site );
$this->old_site = untrailingslashit(empty($old_site) ? home_url() : $old_site);
$this->wp_path = $path;
}
// wp_options
public function options() {
global $wpdb;
$count = 0;
$sql = $wpdb->prepare(
"SELECT * from `{$wpdb->options}` where option_value like \"%s\"",
'%'.untrailingslashit($this->old_site).'%'
);
$results = $wpdb->get_results($sql);
foreach ($results as $result){
$sql = $wpdb->prepare(
"UPDATE `{$wpdb->options}` SET option_value=\"%s\" where option_id = %d",
$this->replace($this->old_site, $this->new_site, $result->option_value) ,
$result->option_id
);
$wpdb->query($sql);
$count++;
}
return $count;
}
// wp_posts
public function posts() {
global $wpdb;
$sql = $wpdb->prepare(
"UPDATE `{$wpdb->posts}` SET post_content=REPLACE(post_content, \"%s\",\"%s\") where post_content like \"%s\"",
$this->old_site,
$this->new_site,
"%{$this->old_site}%"
);
return $wpdb->query($sql);
}
// wp_postmeta
public function postmeta() {
global $wpdb;
$count = 0;
$sql = $wpdb->prepare(
"SELECT * from `{$wpdb->postmeta}` where meta_value like \"%s\"",
'%'.untrailingslashit($this->old_site).'%'
);
$results = $wpdb->get_results($sql);
foreach ($results as $result){
$sql = $wpdb->prepare(
"UPDATE `{$wpdb->postmeta}` SET meta_value=\"%s\" where meta_id = %d",
$this->replace($this->old_site, $this->new_site, $result->meta_value) ,
$result->meta_id
);
$wpdb->query($sql);
$count++;
}
return $count;
}
// wp_usermeta
public function usermeta() {
global $wpdb;
$count = 0;
$sql = $wpdb->prepare(
"SELECT * from `{$wpdb->usermeta}` where meta_value like \"%s\"",
'%'.untrailingslashit($this->old_site).'%'
);
$results = $wpdb->get_results($sql);
foreach ($results as $result){
$sql = $wpdb->prepare(
"UPDATE `{$wpdb->usermeta}` SET meta_value=\"%s\" where umeta_id = %d",
$this->replace($this->old_site, $this->new_site, $result->meta_value) ,
$result->umeta_id
);
$wpdb->query($sql);
$count++;
}
return $count;
}
// wp_commentmeta
public function commentmeta() {
global $wpdb;
$count = 0;
$sql = $wpdb->prepare(
"SELECT * from `{$wpdb->commentmeta}` where meta_value like \"%s\"",
'%'.untrailingslashit($this->old_site).'%'
);
$results = $wpdb->get_results($sql);
foreach ($results as $result){
$sql = $wpdb->prepare(
"UPDATE `{$wpdb->commentmeta}` SET meta_value=\"%s\" where meta_id = %d",
$this->replace($this->old_site, $this->new_site, $result->meta_value) ,
$result->meta_id
);
$wpdb->query($sql);
$count++;
}
return $count;
}
private function replace($origin, $replaced, $value) {
if ( is_serialized($value) ) {
$value = maybe_unserialize($value);
$value = $this->deep_replace($origin, $replaced, $value);
$value = maybe_serialize($value);
} else {
$value = str_replace($origin, $replaced, $value);
}
return $value;
}
private function deep_replace($origin, $replaced, $datas) {
if ( is_array($datas) || is_object($datas) ) {
foreach ( $datas as &$data ) {
if ( is_array($data) || is_object($data) ) {
$data = $this->deep_replace($origin, $replaced, $data);
} else {
$data = str_replace($origin, $replaced, $data);
}
}
}
return $datas;
}
}

Posted

in

by

Tags:

Comments

“[WordPress] WordPress のDB上のサイトURLを一気に変換”. への8件のフィードバック

  1. jim912 のアバター

    define( ‘SHORTINIT’, true ); しとくと余計な読み込みしなくて更に良い希ガス

    1. wokamoto のアバター

      最初、それやったんだけど untrailingslashit() だったかが functions not found になったのでやめました。

      1. jim912 のアバター
        jim912

        あ、なるほど。maybe_serializeとかも使えないかも。それだけ、読み込むって手もあるけど。

  2. Shogo Kato (@show555) のアバター

    こんにちは、便利なスクリプトをありがとうございます。実際に使ってみたところ下記のようなエラーが出たケースがありましたので報告させていただきます。
    Catchable fatal error: Object of class __PHP_Incomplete_Class could not be converted to string in /path/to/replace-siteurl.php on line 180

    気になってデバッグしてみたところ“Google XML Sitemaps”というプラグインのwp_optionテーブルに保存されている値が原因でした。エラーになる流れは以下のようです。

    “Google XML Sitemaps”の“sm_cpages”オプションはプラグイン自前のクラスオブジェクトがそのままシリアライズされたものが保存されている
     ↓
    replace_siteurl.phpがURLを書き換えるために“sm_cpages”オプションの値をアンシリアライズ
     ↓
    “Google XML Sitemaps”のクラスが読み込まれていないのでオブジェクトを復元できず、“__PHP_Incomplete_Class_Name”のオブジェクトが返される
     ↓
    “__PHP_Incomplete_Class_Name”のオブジェクトはis_object関数でfalseが返される
     ↓
    180行目(deep_replaceメソッドのstr_replace)でfatal error

    これに関しては“Google XML Sitemaps”の値の保存の仕方が悪いせいだと思いますが、せめてfatal errorは回避したいのでdeep_replaceメソッドを以下のように変更してみました。(本当は警告とか出す処理も挟むべきだと思うのですがとりあえず…)

        private function deep_replace($origin, $replaced, $datas) {
            if ( is_array($datas) || is_object($datas) ) {
                foreach ( $datas as &$data ) {
                    if ( is_array($data) || is_object($data) ) {
                        $data = $this->deep_replace($origin, $replaced, $data);
    +              } elseif ( !is_object($data) && 'object' === gettype($data) ) {
    +                  continue;
                    } else {
                        $data = str_replace($origin, $replaced, $data);
                    }
                }
            }
            return $datas;
        }
    1. wokamoto のアバター

      うーん、wp-load.php インクルードしてるので “Google XML Sitemaps” の独自オブジェクトもアンシリアライズ&シリアライズできるはずなんですが….
      Google XML Sitemaps が無効になっていませんか?有効にすれば、通るかもしれません。

      …いや、違うか。後で回避方法考えますね。

      1. Shogo Kato (@show555) のアバター

        確認したところGoogle XML Sitemapsは有効化された状態でした。
        Google XML Sitemapsを調べてみたところアンシリアライズ時に定義されているべきクラスは、プラグインロード時には読み込まれず特定のメソッドを実行した後に読み込まれる構造になっていました。

  3. […] 導入されているプラグインによっては、正常に動作しないことがあるかもしれません。 その辺は、meta.dogmap.jp のコメント欄を参考にしてください。 […]

  4. gatespace のアバター

    Gatespace's Blog でリブログ& コメント:
    をかもとさんのWordPress用サイトURL変更スクリプト。
    ローカルのMAMPで実行するときはあらかじめ、wp-config.phpの define(‘DB_HOST’, ‘localhost’); と define(‘DB_HOST’, ‘:/Applications/MAMP/tmp/mysql/mysql.sock’); に変更しておこう!

コメントを残す