WordPressの開発でローカルサーバとリモートサーバのDBをwp-cliをつかって同期を取らせる

# はじめに
DBの同期って面倒ですよね。
開発初期は固定ページやプラグインの設定をゴリゴリする事が多くて、それの同期が大変でした。
プラグインもいくつかあったりしますが、なかなかうまく行きませんでした。

チームのデザイナーさん、コーダーさんがローカルとリモートで簡単に同期を取れるようにできないか、ということでやってみました。

ファイルをダブルクリックでリモート <--> ローカルの同期が出来るようになりました。
環境はMacです。

![Screen Shot 2016-08-25 at 2.37.14 PM.png](https://qiita-image-store.s3.amazonaws.com/0/47327/5e9fed5c-c671-d714-0a9d-8051f9c009d6.png)


# 準備
サイトを参考にしながらリモートにwp-cliを入れておきます。

## wp-cliのインストール

> レンタルサーバに『WP-CLI』をサクっと入れるシェルスクリプト作ってみたよ
> https://www.tecking.org/archives/4169

## sshの設定
> さくらレンタルサーバーにSSHで公開鍵ログインしました
> http://qiita.com/pugiemonn/items/1597939003ca83208e0d

# configの用意
プロジェクト用の`wp-cli.yml`を用意します。
ローカルのWordPressインストールディレクトリを`path`に指定します。
リモートのホスト名+インストールディレクトリを`ssh`に指定します。

```yaml:wp-cli.yml
path: /Users/yousan/public_html/test.dev

@test:
  ssh: testserver.example.com/path/to/test.example.com
```

これをプロジェクトごとのgitリポジトリにディレクトリを掘ってそこ配置しました。

# スクリプトの用意

* ローカル -> リモート
* リモート -> ローカル
 
のスクリプトを用意します。

```bash:to_remote.command
cd -- "$(dirname "$BASH_SOURCE")"
wp db export - | wp @test db import -
wp search-replace  'http://example.dev' 'http://test.example.com'
```

```bash:to_local.command
cd -- "$(dirname "$BASH_SOURCE")"
wp @test db export - | wp db import - 
wp search-replace 'http://test.example.com' 'http://example.dev'
```

これを先ほどのwp-cli.ymlと同じディレクトリに配置します。

途中にある`test.example.com`、`test.dev`はリモートのホスト名、ローカルのホスト名(バーチャルホストのドメイン名)に設定します。

あとはこのファイルを開けばターミナルが勝手に開いて同期を取ることができます。

![wp-cli-sync.gif](https://qiita-image-store.s3.amazonaws.com/0/47327/b1981d2a-a13f-80bc-f0aa-5a1642c0e4a2.gif)

便利ですね！

# プラグイン
プラグインも同期を取りたい、ということだったので追記をしました。

```bash:to_remote.command
wp plugin list --status=active --format=csv | tail -n +2 | awk 'BEGIN {FS=",";} {printf "%s ", $1;}' | xargs wp @test plugin install --activate
```

```bash:to_local.command
wp @test plugin list --status=active --format=csv | tail -n +2 | awk 'BEGIN {FS=",";} {printf "%s ", $1;}' | xargs wp  plugin install --activate
```

# メディア
メディアファイルの同期は出来ないの？という事を聞かれましたので追記です。

```bash:to_local_media.command
cd -- "$(dirname "$BASH_SOURCE")"
rsync -avz   --exclude='cache/*' --exclude='backup/*'\
test.example.com:/path/to/test.example.com/wp-content/uploads/ \ 
/Users/yousan/public_html/test.dev/wp-content/uploads
```

```bash:to_remote_media.command
cd -- "$(dirname "$BASH_SOURCE")"
rsync -avz   --exclude='cache/*' --exclude='backup/*'\
/Users/yousan/public_html/test.dev/wp-content/uploads \
test.example.com:/path/to/test.example.com/wp-content/uploads/ 
```

ファイルについてはwp-cliで同期できないので、`rsync`を使います。
rsyncであれば差分ファイルだけを転送するので効率が良いですね。
wp-cli.ymlを参照しないので注意が必要です。

# 雑感
DBが中規模以上だと転送に結構時間がかかりました。

ステージングと本番などのリモート同士の同期もこのやり方で行けそうですが、手元を介すると転送量が二重になりそうなので注意が必要そうです。

セキュリティリスクはありますが、秘密鍵をgitに含めるともっと便利かと思ったんですが、wp-cli.ymlで秘密鍵指定出来ませんでした。もしどなたか知っていたら教えてください。

gitで自動デプロイと組み合わせると快適ですね。

wp-cli.ymlについては、ローカルの開発環境のパスがチームメンバーによって違ったのでgitの共有を迷いました。
`wp-cli.yml`は`.gitignore`に入れておいて、`wp-cli-sample.yml`をgitで管理し、wp-cli.ymlは初回にメンバーの環境に合わせて変更しました。

DBのテーブルによってはキャッシュテーブルが含まれる事があったりして、数GBのーブルを転送されると困るので注意が必要です。
それらを外すことも検討したいです。

この機能を実現するのはWordMoveがありますが、うまく行きませんでした。最初は動いていても途中から動かなくなったりとちょっと困っていました。

## 変更
@Toro_Unit さんから「updateより search-replaceの方が良いんじゃない？」というアドバイスをもらいました。ありがとうございます。

以前の`option update`は以下の通りです。

```bash
wp option update siteurl 'http://example.dev' ; wp option update home 'http://test.example.com'
```

`search-replace`を使うと記事中の画像のURLも全て変更することができます。
ただし `search-replace` は少し重いです。記事数が1000ぐらいになると、この置換に数分かかりました。リビジョンがあるともっと重いと思います。

状況に応じて使ってください。

# 参考

最近のwp-cliのアップデートで、リモート先にwp-cliを利用できるようになりました。
プロジェクト事にwp-cli.ymlを設定しておくとリモートでwp-cliが使えるので非常に便利です。

> VCCWとWP-CLIをもっと仲良しにする設定
> http://qiita.com/miya0001/items/8541ee689b17cb7f24fe