開発環境から本番環境に移行する時、サイトURLを変換したい時に使おう。
使い方
$ php replace-siteurl.php {new_site_url} /path/to/wordpress/
#!/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://'.$new_site ); | |
$old_site = (!empty($old_site) && !preg_match('/^https?:\/\//i', $old_site) ? 'http://'.$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; | |
} | |
} |
define( ‘SHORTINIT’, true ); しとくと余計な読み込みしなくて更に良い希ガス
最初、それやったんだけど untrailingslashit() だったかが functions not found になったのでやめました。
あ、なるほど。maybe_serializeとかも使えないかも。それだけ、読み込むって手もあるけど。
こんにちは、便利なスクリプトをありがとうございます。実際に使ってみたところ下記のようなエラーが出たケースがありましたので報告させていただきます。
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メソッドを以下のように変更してみました。(本当は警告とか出す処理も挟むべきだと思うのですがとりあえず…)
うーん、wp-load.php インクルードしてるので “Google XML Sitemaps” の独自オブジェクトもアンシリアライズ&シリアライズできるはずなんですが….
Google XML Sitemaps が無効になっていませんか?有効にすれば、通るかもしれません。
…いや、違うか。後で回避方法考えますね。
確認したところGoogle XML Sitemapsは有効化された状態でした。
Google XML Sitemapsを調べてみたところアンシリアライズ時に定義されているべきクラスは、プラグインロード時には読み込まれず特定のメソッドを実行した後に読み込まれる構造になっていました。
Gatespace's Blog でリブログ& コメント:
をかもとさんのWordPress用サイトURL変更スクリプト。
ローカルのMAMPで実行するときはあらかじめ、wp-config.phpの define(‘DB_HOST’, ‘localhost’); と define(‘DB_HOST’, ‘:/Applications/MAMP/tmp/mysql/mysql.sock’); に変更しておこう!