WordPressのGit管理を考える

Gitでのソースコード管理が浸透しつつある昨今、WordPressはGit管理できるのか考えてみます。

WordPressは基本的にサーバーにインストールし、管理画面をメインに運用するソフトウェアですが、既存のテーマのまま使うことはあまりなくカスタマイズが必要です。
そうなると、やはりソースコードをGitでバージョン管理した方が、多人数での開発も楽になりますし安心でしょう。

ボイラープレート(既存テンプレート)での構成

BedrockGitHub)というテンプレート(ボイラープレート)があります。
このテンプレートはGit管理を前提にしており、”今風” の管理方法でWordPressを利用します。
WordPress本体には触れないため、本体更新なども問題ありません。

面白いのは、wp-content ディレクトリの管理をまるごと外に出している点です。
WP_CONTENT_DIRWP_CONTENT_URLで変更可)
これによって本体とプログラムを切り離しています。

Bedrockは構成も開発者向けによく考えられているのですが、例えばPHPフレームワークと共存したい場合にはファイル配置などがやや面倒です。

他プログラムとの共存を考慮した構成

どこを管理するか

WordPressの多くの機能は「テーマ」で制御できます。
そのため、Gitで管理するのはテーマフォルダのみで良いのではないかと思います。
パスとしては以下のフォルダです。

wp-content/themes/[任意のテーマフォルダ]

プラグインに関してはサーバー上で更新するため、Gitで管理するのは避けた方が良いと思います。
もし独自プラグインを作りたい場合も、テーマフォルダ内で展開して良いと思います。
また、画像などが入る wp-content/uploads フォルダや、言語ファイルの wp-content/languages フォルダ、更新時の一時ファイル置き場に使われる wp-content/upgrade フォルダなども頻繁に更新されるためGit管理下には置きません。

全体の構成

Git管理は、WordPress本体フォルダより上の階層にします。
全体としては以下のようなイメージです。
(サイトルートが「public」フォルダの場合)
[home]
 │
 ├ /.git
 ├ /public(サイトルート)
 │ ├ /cms(WordPress本体)
 │ │ ├ /wp-admin
 │ │ ├ /wp-content
 │ │ │ ├ /languages
 │ │ │ ├ /plugins
 │ │ │ ├ /themes
 │ │ │ │ ├ /maintheme(任意のテーマフォルダ名)
 │ │ │ │ └ index.php
 │ │ │ │
 │ │ │ ├ /upgrade
 │ │ │ ├ /uploads
 │ │ │ └ index.php
 │ │ │
 │ │ ├ /wp-includes
 │ │ │・・・
 │ │ ├ /wp-config.php
 │ │  ・・・
 │ ├ .htaccess
 │ └ index.php
 │
 ├ .gitignore
 ・・・
WordPress本体の入るフォルダ名は任意ですが、ここでは cms としています。
よって、管理画面のURLは https://example.com/cms/wp-admin となります。
注意点として、WordPress本体のフォルダ名は「wp」など2文字にはしない方がよいでしょう。
例えば多言語サイトを構成した場合、https://example.com/en といった言語ごとのURLにする場合があります。
そうなった時に管理画面が「wp」の2文字だと、プログラム側が言語名だと勘違いする可能性があるからです。

テーマフォルダ名も任意ですが、ここでは maintheme としています。

除外(.gitignore)設定

フォルダ構成が上記の場合、.gitignore ファイルは以下のようになります。
# WordPressによって書き換わる場合があるため除外
/public/.htaccess
/public/sitemap*

# テーマフォルダと wp-config.php のみにする
/public/cms/*
!/public/cms/wp-config.php
!/public/cms/wp-content
/public/cms/wp-content/*
!/public/cms/wp-content/themes
/public/cms/wp-content/themes/*
!/public/cms/wp-content/themes/maintheme

composerを利用する場合

composerで外部ライブラリを利用する場合、vendor ディレクトリをルートにするか、テーマ内にするか悩ましいところです。
個人的にはルートに配置するのが良いと考えます。
[home]
 │
 ├ /.git
 ├ /public(サイトルート)
 │ ├ /cms(WordPress本体)
 │ ・・・
 ├ /vendor
 ├ composer.json
 ・・・
理由としては、サイト内にWordPress以外のプログラムを作れるようにするためです。
その際、WordPressと共用でcomposerライブラリを使える方が効率が良いと思います。

wp-config.php の在り方

WordPressの環境設定ファイルである wp-config.php についても悩ましいところですが、メジャーどころのPHPフレームワークに倣って .env ファイルで管理するのが良いと思います。
.env ファイルはサーバーホーム直下に置きます。

[home]
 │
 ├ /.git
 ├ /public(サイトルート)
 │ ├ /cms(WordPress本体)
 │ ・・・
 ├ .env
 ・・・
.envファイルの内容は以下のような感じです。

# サイト基本設定
APP_ENV=local
APP_DEBUG=
APP_URL=https://example.com

# データベース設定
DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=example_database
DB_USERNAME=username
DB_PASSWORD=password
DB_CHARSET=utf8mb4
DB_COLLATION=utf8mb4_general_ci

# WordPressテーブル接頭辞
WP_TABLE_PREFIX=wp_

# WordPress認証用ユニークキー
WP_AUTH_KEY=XXXXXXXXXXXXXXXXXXXXXX
WP_SECURE_AUTH_KEY=XXXXXXXXXXXXXXXXXXXXXX
WP_LOGGED_IN_KEY=XXXXXXXXXXXXXXXXXXXXXX
WP_NONCE_KEY=XXXXXXXXXXXXXXXXXXXXXX
WP_AUTH_SALT=XXXXXXXXXXXXXXXXXXXXXX
WP_SECURE_AUTH_SALT=XXXXXXXXXXXXXXXXXXXXXX
WP_LOGGED_IN_SALT=XXXXXXXXXXXXXXXXXXXXXX
WP_NONCE_SALT=XXXXXXXXXXXXXXXXXXXXXX
「認証用ユニークキー」は、前述したBedrock の Salt Generator を利用すると楽です。(各変数の先頭に「WP_」を追加する必要があります)

.envの読み取りには、composerライブラリ vlucas/phpdotenv を使用します。
このライブラリの読み込みも含めて wp-config.php には以下のように記載することで、ローカル環境とリモート環境で共通して使えます。

<?php
// サーバーホームパス
$root_dir = dirname(__DIR__, 2);

/**
 * phpdotenvの読み込みと実行
 */
require_once($root_dir.'/vendor/vlucas/phpdotenv/src/Dotenv.php');
require_once($root_dir.'/vendor/vlucas/phpdotenv/src/Loader.php');
require_once($root_dir.'/vendor/vlucas/phpdotenv/src/Validator.php');

$dotenv = new Dotenv\Dotenv($root_dir);
if (file_exists($root_dir.'/.env')) {
    $dotenv->load();
    $dotenv->required(['DB_DATABASE', 'DB_USERNAME', 'DB_PASSWORD']);
}

// データベース設定
define('DB_NAME', getenv('DB_DATABASE'));
define('DB_USER', getenv('DB_USERNAME'));
define('DB_PASSWORD', getenv('DB_PASSWORD'));
define('DB_HOST', getenv('DB_HOST'));
define('DB_CHARSET', getenv('DB_CHARSET'));
define('DB_COLLATE', getenv('DB_COLLATION'));

// データベーステーブルの接頭辞
$table_prefix  = getenv('WP_TABLE_PREFIX');

// 認証用ユニークキー
define('AUTH_KEY', getenv('WP_AUTH_KEY'));
define('SECURE_AUTH_KEY', getenv('WP_SECURE_AUTH_KEY'));
define('LOGGED_IN_KEY', getenv('WP_LOGGED_IN_KEY'));
define('NONCE_KEY', getenv('WP_NONCE_KEY'));
define('AUTH_SALT', getenv('WP_AUTH_SALT'));
define('SECURE_AUTH_SALT', getenv('WP_SECURE_AUTH_SALT'));
define('LOGGED_IN_SALT', getenv('WP_LOGGED_IN_SALT'));
define('NONCE_SALT', getenv('WP_NONCE_SALT'));

// デバッグモード
define('WP_DEBUG', !!getenv('APP_DEBUG'));

// ホームURLの設定

define('WP_HOME', getenv('APP_URL'));
define('WP_SITEURL', getenv('APP_URL').'/'.basename(__DIR__));

// WordPress固有の設定
if ( !defined('ABSPATH') )
    define('ABSPATH', dirname(__FILE__) . '/');

require_once(ABSPATH . 'wp-settings.php');
.env ファイルの内容を見てピンときた方もいるかもしれません。
実はLaravelの.envファイルを基本形としているためです。
上記の構成であれば、Laravelフレームワークの中にWordPressを入れてもほとんど影響しあうことはありません。
ただし、WordPress⇔Laravel間のデータのやりとりは一筋縄ではいきません。
(これはまた別の機会で考察したいと思います)
以上、WordPressのGit管理について考えてみましたが、他にもっと良い方法もあるかもしれませんね。
むしろ、今となってはWordPressのソース自体がレガシーなシステムとなってきていますので、どこかで刷新されると助かります。