WordPressの検証環境・本番環境のDB同期をSearch-Replace-DB+Shellで解決！（我流）


wordpressはCMSのため、管理ページからページを新規追加するスタイルです。
アメーバやSeessa等のブログサービス同等、デザイナーさんに投稿をお任せできるのでシステムな人はリリース作業が必要ありません。
わーい！やったー！デプロイしなくていいから楽。

##新しいテンプレートを本番環境に追加する手順
新しいテンプレートを追加したいとき、それもページ数が１０・２０...デザインもバラバラ。
このとき、リリースするまでの過程がやたら長くなる。

### Wordpressリリース完了までの流れ

検証環境に本番環境のDB、テンプレート情報を取り込む
↓
DB内のサイトURLを検証環境URLに変換して、検証環境DBに取り込む
↓
検証環境でデザインテンプレート作成（デザイナーさん作業）
↓
本番環境にテンプレートアップロード
↓
DB内のサイトURLを本番URLに変換して、本番DBに取り込む
↓
リリース完了

### システム屋さんの作業が多い...

デザイナーさんはテンプレート作成だけに終わるが、システム屋さんは準備とリリースの作業が大変！
それも毎回、このような作業を行っては効率が悪いです。

### これが出来ればシステム屋さんも楽になる

* 本番と検証のDBを同期
* 本番と検証のテンプレートと画像を同期

つまり、本番 ⇔ 検証 の同期がすぐに出来れば楽です。
これが出来るものがないか探したところ、いくつかありました。

## WPで検証・本番環境の同期を行う方法

### Wordmoveを使う：難易度★★☆

WordmoveはRuby製のツールでCapistrano2をベースにしたものです。
何ができるかというと

* uploads、themes、plugins等、パーツ単位で本番・検証環境の同期が出来る
* サイトURLを本番環境URLに変換して、本番DBに反映させる

※詳しくはこちらの記事を参照
http://qiita.com/akiko-pusu/items/43d87896a518233d9503

これで問題解決！Q.E.D！かと思いきや、DB内のシリアライズされたサイトURLは変換してくれない模様。

### Search-Replace-DBでシリアライズされたDB内容を正しく書き換える：難易度★☆☆

カスタムフィールドでURLを保存すると、内容はシリアライズされてDBに保存されます。
そのため、URLの文字数が検証と本番環境で違う場合、下手に置き換えるとPHPエラーが発生します。

下手に置き換えてPHPエラーが発生する例↓

シリアライズ前
`array('hoge.com')`

シリアライズ後
`a:1:{i:0;s:8:"hoge.com";}`

hoge.comをstaging.hoge.comに置き換えてunserializeすると...

```
php > var_dump(unserialize('a:1:{i:0;s:8:"staging.hoge.com";}'));
PHP Notice:  unserialize(): Error at offset 22 of 33 bytes in php shell code on line 1
PHP Stack trace:
PHP   1. {main}() php shell code:0
PHP   2. unserialize('a:1:{i:0;s:8:"staging.hoge.com";}') php shell code:1
bool(false)
```

bool(false）と返ってきました！

ここで、PHP製ツールの「Search-Replace-DB」を使います。
下記のコマンド一発でDB内のURLを書き換えてくれます。

```
php srdb.cli.php -h='localhost' -u='root' -p='hoge' -n='hoge_db' -s='hoge.com' -replace='staging.hoge.com'
```

素晴らしいのがシリアライズされたURLも正しく書き換えてくれます！
検証と本番で文字数が違ってもそれに合わせてserializeした結果を再度DBに保存する優れもの。

ただし、DB内容を直接書き換えるのでその結果を本番にアップロードする必要があります。
また、書き換え先が検証DBの場合は元に戻す作業も...

###シェル+Search-Replace-DBでデータベースの同期をコマンド一発解決！：難易度★★★

Search-Replace-DBはDBを直接書き換えるため、検証環境DBの書き換えた結果を本番DBに取り込む必要があります。
これらをコマンド一発でやる方法にシェルを採用！（仕方なく...）

▼ 検証環境 から 本番環境 にDBを取り込む手順 ▼

![スクリーンショット 2014-05-03 13.05.52.png](https://qiita-image-store.s3.amazonaws.com/0/29861/45582562-5884-eb90-3060-af6e622bb377.png "スクリーンショット 2014-05-03 13.05.52.png")


#### 準備：Search-Replace-DBをダウンロード

git-hubから下記ファイルをダウンロードしてください。
* https://raw.githubusercontent.com/interconnectit/Search-Replace-DB/master/srdb.class.php
* https://raw.githubusercontent.com/interconnectit/Search-Replace-DB/master/srdb.cli.php

#### 検証 から 本番に取り込むシェルスクリプトの内容

```wp-db-push.sh
#!/bin/sh
NOW=`date +"%Y%m%d_%H%M"`
SEARCH=$1
REPLACE=$2

#dumpファイルの保存先
BAK_LOCAL="/tmp/local.bk.$NOW.sql"
BAK_REMOTE="/tmp/remote.bk.$NOW.sql"
REPLACE="/tmp/replace.$NOW.sql"

#検証環境のDBをバックアップ
echo "mysqldump -uroot -phoge hoge_db > $BAK_LOCAL"
mysqldump -uroot -phoge hoge_db > $BAK_LOCAL

#ファイルがない場合は終了
if [ ! -s $BAK_LOCAL ]; then
  echo "dump failed: check $BAK_LOCAL"
  exit
fi

#DB内容を書き換え
echo "php srdb.cli.php -h='localhost' -u='root' -p='hoge' -n='hoge_db' -s=$SEARCH -r=$REPLACE"
php srdb.cli.php -h='localhost' -u='root' -p='hoge' -n='hoge_db' -s=$SEARCH -r=$REPLACE

#検証DBをdump
echo "mysqldump -uroot -phoge hoge_db > $REPLACE"
mysqldump -uroot -phoge hoge_db > $REPLACE

#検証DBを元に戻す
echo "mysql -uroot -phoge hoge_db < $BAK_LOCAL"
mysql -uroot -phoge hoge_db < $BAK_LOCAL

#ファイルがない場合はDBを元に戻して終了
if [ ! -s $BAK_LOCAL ]; then
  echo "dump failed: check $REPLACE"
  echo "mysql -uroot -phoge hoge_db < $BAK_LOCAL"
  exit
fi

#本番DBに接続して、データをバックアップ（SSHで接続しない場合は-hを変えてください）
echo "ssh hoge@hoge.com mysqldump -uroot -phoge -hlocalhost hoge_db > $BAK_REMOTE"
ssh hoge@hoge.com mysqldump -uroot -phoge -hlocalhost hoge_db > $BAK_REMOTE

#ファイルがない場合は終了
if [ ! -s $BAK_REMOTE ]; then
  echo "dump failed: check $BAK_REMOTE"
  exit
fi

#本番環境に取り込む
echo "ssh hoge@hoge.com mysql -uroot -phoge -hlocalhost hoge_db < $REPLACE"
ssh hoge@hoge.com mysql -uroot -phoge -hlocalhost hoge_db < $REPLACE
```

逆に、本番 から 検証にDBを取り込むシェルスクリプトの内容

```wp-db-pull.sh
#!/bin/sh
NOW=`date +"%Y%m%d_%H%M"`
SEARCH=$1
REPLACE=$2

#dumpファイルの保存先
BAK_LOCAL="/tmp/local.bk.$NOW.sql"
BAK_REMOTE="/tmp/remote.bk.$NOW.sql"

#検証環境のDBをバックアップ
echo "mysqldump -uroot -phoge hoge_db > $BAK_LOCAL"
mysqldump -uroot -phoge hoge_db > $BAK_LOCAL

#ファイルがない場合は終了
if [ ! -s $BAK_LOCAL ]; then
  echo "dump failed: check $BAK_LOCAL"
  exit
fi

#本番DBに接続して、データをダンプ（SSHで接続しない場合は-hを変えてください）
echo "ssh hoge@hoge.com mysqldump -uroot -phoge -hlocalhost hoge_db > $BAK_REMOTE"
ssh hoge@hoge.com mysqldump -uroot -phoge -hlocalhost hoge_db > $BAK_REMOTE

#ファイルがない場合は終了
if [ ! -s $BAK_REMOTE ]; then
  echo "dump failed: check $BAK_REMOTE"
  exit
fi

#検証DBに本番DBを取り込む
echo "mysql -uroot -phoge hoge_db < $BAK_REMOTE"
mysql -uroot -phoge hoge_db < $BAK_REMOTE

#DB内容を書き換え
echo "php srdb.cli.php -h='localhost' -u='root' -p='hoge' -n='hoge_db' -s=$SEARCH -r=$REPLACE"
php srdb.cli.php -h='localhost' -u='root' -p='hoge' -n='hoge_db' -s=$SEARCH -r=$REPLACE
```

以上でございます。

まとめますと

* テンプレート・画像同期は「Wordmove」
* DB同期は「シェル＋Search-Replace-DB」

な運用でシステム屋さんの工数が削減できると思います。

ちなみに、wordpressをcapistrano使ってデプロイする場合は
上記シェルを一緒に組み込むと幸せになれます（実際にやってます）