Local by Flywheel＋CLIで、WordPressをローカル環境に安全に構築してみた

# はじめに
とある機会をいただいて、WordPressでサイトを構築することになったのですが、
Elementorというノーコードツールを作成していました。

しかし、無料版ではイメージしているサイト機能作成には限界があり、
~~遅々として作業が進まずフラストレーションが爆発しそうでしたので、~~
ローカル環境に移行しそちらで~~生成AIに実装を丸投げ~~作業をすることにしました。

といわけで今回は、[Local by Flywheel](https://localwp.com/)でWordPressをWindowsOSのローカル環境に移行を試してみます。

基本的にCLIで作業をしていきます。
この理由は、特にないです（笑）。


# 事前準備
WordPress本番サイトからのデータ取得を取得します。
前提条件として、**ドメインサーバーを管理する会社によって、SSHでの接続は異なりますのでご注意ください。**

くどい内容になりますが、Stepごとに進めていきます。理由は、同時進行で手を動かしながらこの記事を書いているからです（笑）。書き手の都合ですみませんm(__)m。
- [Step1: 本番ファイルのダウンロード](#step1-本番ファイルのダウンロード)
- [Step2:  データベースのエクスポート](#step2-データベースのエクスポート)
## Step1: 本番ファイルのダウンロード
まずは、WordPressのファイルをすべてダウンロードします。
PowershellでSSH/SCPを使用した実行コマンドを入力します。
事前にSSHコマンドでFTPの接続確認をしておくと安心でしょう。

```
# すべてのファイルをダウンロード
scp -r username@user.com:/path/to/wordpress/ ./local-wordpress/

# 個別ファイルのダウンロードはこっち
scp username@user.com:/path/to/wordpress/任意のファイル名.php ./
```

:::note info
`scp`と`rsync`の違い
両方のコマンドで使用可能だそうです。
`scp`はストレートにダウンロードできるのでシンプルです。
シンプルが一番なので、こっちを使ってます。
:::

一旦すべてのファイルをダウンロードします。

## Step2: データベースのエクスポート
続いて、データのエクスポートです。

```
# 接続コマンド
mysqldump -h [DB_HOST] -u [username] -p --no-tablespaces --single-transaction --skip-triggers --skip-routines [database_name] > backup.sql
```

:::note info
`--no-tablespaces`について
サーバーへのアクセスは物理ファイル情報で制限されます。
ですので、物理ファイルはスキップしてデータだけを取得するようにします。

:::


以上で事前準備完了です。

# いざ実践
流れは以下のようになります。

- [Step1: ダウンロード](#step1-ダウンロード)
- [Step2: 新しいサイトを作成](#step2-新しいサイトを作成)
- [Step3: ファイルの復元](#step3-ファイルの復元)
- [Step4: データベースの復元](#step4-データベースの復元)
- [Step5: ローカル用URLに変換](#step5-ローカル用URLに変換)

## Step1: ダウンロード
字の如くです。まずは下記サイトからダウンロードを行います。

https://localwp.com/


`.exe`がダウンロードされるのでインストールしましょう。

アカウント作成を要求されるので、作成しましょう。
今回はGithub連携でさくっとやります。


## Step2: 新しいサイトを作成
`Create a new site`を押下して、サイトを立ち上げましょう。
最初に、サイト名・ローカルドメインを設定します。
これは、現在のWordPress名と合わせましょう。

次に`PHP/MySQL/nginx or Apache`のバージョンを本番環境に合わせます。
デフォルトでは、いずれも最新バージョン、webサーバーはnginxが設定されています。
本番環境のWordPressは基本的にApacheなのでCustomで設定します。

:::note warn
**上記のバージョンは必ず確認するようにしましょう！**
`WordPress管理画面 > ツール > サイトヘルス`でプルダウン内で確認できます。
特にwebサーバーは異なったら全く動作が変わりますのでご注意を。
:::


## Step3: ファイルの復元
ダウンロードしたファイルを復元します。
念のため`wp-content`はバックアップしておきます。

```
mkdir wp-content-local-backup
xcopy wp-content wp-content-local-backup /E /I /H /Y
```

Local sitesのSite shellを開くと、Local by Flywheelが開いている現在のディレクトリからshellが立ち上がるので、まず、最初に保存してある`wp-content`を削除します。
これは、デフォルトで作られているのに上書き保存させないためです。
```
rmdir wp-content /S /Q
```
そこから以下のコマンドを実行します。
```
# 本番環境のwp-contentをコピー
xcopy "C:\Users\~\~\wp-content" wp-content /E /I /H /Y
```
これで本番環境を移せました。
気になる方は`dir`で確認しておくと安全でしょう。

## Step4: データベースの復元
続いて、エクスポートしたデータベースを復元します。
こちらもCLIでインポートします。

```
wp db import "WordPress.sql"
```

が、ここで問題が発生...
実行しようとしていると、以下のようなエラーが発生して解決がわからず手が止まる...。
```
Error: Failed to get current SQL modes. Reason: ERROR 2003 (HY000): Can't connect to MySQL server on 'localhost:3306' (10061)
```

調べたところ、どうやら、**Config.php内のポート番号と異なることが原因でした。**
localで立ち上げたHost名・ポート番号とそもそも違うということが原因らしいです！

ですので、以下のようにローカル環境用のポート番号`10004`設定を追加します。
```
// ローカル環境用設定
define('DB_HOST', 'localhost:10004');
define('DB_NAME', 'local');
define('DB_USER', 'root');
define('DB_PASSWORD', 'root');
```

これで決まった！と思っていたところ、、、。
```
ERROR at line 1: Unknown command '\U'.
```
業務でもよく見たことあるこれは、文字コードの問題！
エクスポートするとき、utf-8でしたはずですが、.sqlを確認すると特に大きな問題は見当たらず。
加えて、さらにエラーが発生しますが、記事が長すぎてしまうのでここでは割愛します。

別記事にて一番詰まった内容を公開しますm(__)m。


ここばっかりは、GUIで実行することにしました。
Local by FlywheelのAdminerNeoを開いて、指定した.sqlファイルを選択してインポートします。
すると…。

無事に立ち上がりました！


## Step5: ローカル用URLに変換
データ回りで手間取りましたが、最後のステップです。

本番データをすべてローカル環境に移し終えたので、URLも重複してしまっています。
これだと本番サイトと見分けがつかなくなってしまうため、ローカル環境のURLと明示的にわかるように変更しておきます。

```
# 基本設定変更
wp option update home "~.local"
wp option update siteurl "~.local"

# 投稿・ページ・データベース内のURL一括置換
wp search-replace "本番URL.com" "~.local"

```
最後に.localURLで開くか確認しましょう。
startを押下して、`WP Admin`を開きます。

設定したローカルURLで開けていれば問題ありません！

# 終わりに

いやー、、、**作業しながら記事を書くと、想像以上に時間がかかりました笑（丸一日使ってます👀）**。
やり方自体が非効率なのと、WordPress and Local by Flywheelも初めて、慣れてないCLI操作を生成AIに聞きながらの作業なので、無理くりなマルチタスクが時間ロス要因となることになりました。

加重のアウトプット方式で理解力をつけるつもりが余計に時間がかかり、解説記事というのは、やはりきちんと理解してからが大前提となるということが、改めて再認識できました。

途中までは順調でしたが、データインポートはかなり苦戦しました。
エラーが出たら記事にするの精神で、今度はゆっくりと思い出しながら記載ｎしたいと思います。