現在のWordPress標準制作フロー
5年前に記載したこちらの記事は、もう昨今の作業環境には適合しなくなりました。
2024年現在での弊社の標準的な制作フローをご紹介します。
WordPressを扱うエンジニアに対する質問事項で記載した回答例と一部重複しますが、より詳細に案内したいと思います。
前提事項
5年前の記載内容と前提事項は同様です。
- Web制作会社などでいちからサイトを制作することを想定
汎用テーマなどを使って簡易に構築するとかではなく、ガッツリとそのサイト専用のテーマを作成する - それぞれのツールのインストール方法などは記載しない
Qiita内で丁寧に手順を記載している記事があるので検索してみてください
ローカル開発環境
WordPressでサイト制作を決めた場合、携わるエンジニアは開発環境として何を使えばよいでしょうか?
我々の回答としては、基本的には@wordpress/env、場合によってはLOCALを考えています。
最終的にShifterで動作させる想定の場合はShifter(Static) - Local、Kinstaでの動作を想定している場合はDevKinstaという選択肢もあるかもしれません。1
@wordpress/env
WordPress公式が提供する今考えられる一番標準的な開発環境です。
Node.jsとDockerを動かすため、これらの基礎的な知識が必要となります。
メリット
- PHPバージョン設定などがコードとして定義されるため、IaC的観点で良い
- CLIからの操作が主のため、スクリーンショット付きの手順書などが不要となる
- WordPress公式なので安心できる
デメリット
- Node.jsやDockerなどの知識が必要になる
- CLIからの操作が主のため、非エンジニアには扱いづらい
- 良くも悪くも、開発対象の独自テーマや独自プラグイン以外の構成がIDEから見えにくくなるので、IDE内の関数未定義エラーなどを解決するにはスタブの設定が必要
設定例
@wordpress/envは.wp-env.json
にて設定を行います。
下記に設定を記載します。
{
"phpVersion": "8.1",
"port": 8765,
"env": {
"tests": {
"port": 8764
}
},
"config": {
"WP_DEBUG": true,
"SAVEQUERIES": true
},
"mappings": {
"../data": "./misc/data",
".htaccess": "./misc/.htaccess",
"../install.sh": "./misc/install.sh",
"wp-content/uploads": "./uploads",
"wp-content/themes/example_wp_theme_name": "./themes/example_wp_theme_name"
}
}
- phpVersion
- PHPのバージョンを指定します。本番環境に合わせると良いでしょう。
- port
- サイトごとに重複しないポートにすると同時に立ち上げることができて良いでしょう。
- config
-
wp-config.php
の設定値を定義します。 Warningなどを検出できるよう、デバックモードはtrueにします。 - mappings
- ホストOSのディレクトリをDockerインスタンス上にマウントします。
- ここではDBダンプなど、なんらかのファイルをDocker側とやりとりする際の
data
ディレクトリ、.htaccess
、初期セットアップ用のシェルスクリプト(後述)、メディアファイル、テーマファイルをマッピングしています。data
ディレクトリとuploads
ディレクトリの中のファイルは.gitignore
でバージョン管理外にすると良いでしょう。 - ここではDBダンプなど、なんらかのファイルをDocker側とやりとりする際の
スタブ
デメリットで挙げたようにVSCodeのPHP Intelephenseを用いている場合、WordPressの標準関数を定義しているファイルをIDEが把握できないため、エラー扱いとなります。
これは、VSCode設定画面のintelephenseからwordpress
を追加することで回避できます。
また、WordPressのオリジナルテーマ開発にはAdvanced Custom Fieldsを用いることも多いでしょう。
この場合は、get_field
やthe_field
などの関数もエラーにならないようにphp-stubs/acf-pro-stubsも導入すると良いでしょう。
LOCAL
Docker環境は想定外のトラブルシューティングにある程度の知識を求められるため、Node.jsやDockerなどの基礎的な知識を持たないメンバーが参画する場合はLOCALのようなGUIアプリケーションの利用も考えられます。
メリット
- GUIアプリケーションで簡単に扱える
- 仮想技術などが入っておらず、WordPress本体のコードも含めFinder上から確認しやすい
デメリット
- GUIからの操作が主のため、情報共有にはスクリーンショット付きの手順が必要となる
- 設定がコード化されていないため、メンバー間で想定外の動作環境の差異が発生しやすい
テーマ作成の第一歩
WP CLIのwp scaffoldコマンドを用いて、underscoresベースのテーマ雛形を作成し、そこから不要部分の除去とリファクタリングを実施し、要件にあわせた機能追加を進めていきます。
過去案件をベースにつくれないか
ゼロからWP CLIで構築するより、過去に自身が携わったサイトのテーマを複製するほうが効率的と考えるかもしれません。
それが適切な場合もありますが、下記の理由から前述のような雛形生成ツールを用いるのがおすすめです。
- 固有名詞の置換もれが発生しやすい(受託の場合は深刻なトラブルにも)
- 潜在的な不具合、既知の不具合を引き継ぐ
- 新規構築することにより、もう一度考えなす機会が発生しより効率的でよいコードに成長する
付属ツール
underscores
には下記の便利なツールが付属しています。制作時の効率化のため活用しましょう。
ここではよく使う2つをご紹介します。
PHP Parallel Lint
例えば、 <?php $failedCode = ?>
のような不正なコードをが混入していると実行時に下記のようにエラーを検出します。
> @php ./vendor/bin/parallel-lint --exclude .git --exclude vendor .
PHP 8.0.29 | 10 parallel jobs
............X.... 17/17 (100 %)
Checked 17 files in 0.1 seconds
Syntax error found in 1 file
------------------------------------------------------------
Parse error: ./header.php:27
25| <div id="page" class="container mx-auto bg-white">
26| <a class="skip-link screen-reader-text" href="#primary"><?php esc_html_e( 'Skip to content', 'sample-theme' ); ?></a>
> 27| <?php $failedCode = ?>
28| <header id="masthead" class="bg-gray-300 px-4 py-2 flex flex-col gap-4">
29| <div class="site-branding">
Unexpected token ";" in ./header.php on line 27
Script @php ./vendor/bin/parallel-lint --exclude .git --exclude vendor . handling the lint:php event returned with error code 1
✖ Command failed with exit code 1
Command failed with exit code 1
PHP_CodeSniffer
WordPressのコーディング規約に違反している箇所を教えてくれます。
例えば、下記のようにWordPressのコーディング規約に違反するコードを混入させた実行結果です。
if ( ! defined( '_S_VERSION' ) ) {
// Replace the version number of the theme on each release.
define( '_S_VERSION', '1.0.0' );
define( 'CS_FAILED', 'data' ); $fooBar = null;
}
下記のようにインデントしていないことや変数がスネークケースになっていないこと、1行で書いてはいけないことが指摘されます。
FILE: functions.php
-------------------------------------------------------------------------------------------------------------------------------------------------------------
FOUND 7 ERRORS AFFECTING 5 LINES
-------------------------------------------------------------------------------------------------------------------------------------------------------------
3 | ERROR | [ ] Doc comment short description must start with a capital letter (Generic.Commenting.DocComment.ShortNotCapital)
13 | ERROR | [x] Line indented incorrectly; expected at least 1 tabs, found 0 (Generic.WhiteSpace.ScopeIndent.Incorrect)
13 | ERROR | [ ] Variable "$fooBar" is not in valid snake_case format, try "$foo_bar"
| | (WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase)
13 | ERROR | [x] Each PHP statement must be on a line by itself (Generic.Formatting.DisallowMultipleStatements.SameLine)
デフォルトでは、ルールが厳しすぎるところもあるので、案件に応じてphpcs.xml
をカスタマイズすると良いでしょう。
私の場合、<rule ref="WordPress">
配下に下記のコードを追加することが多いです。
<!-- テーマ内でのカスタム投稿定義を許容 -->
<exclude name="WPThemeReview.PluginTerritory.ForbiddenFunctions.plugin_territory_register_post_type" />
<!-- テーマ内でのブロックタイプ定義を許容 -->
<exclude name="WPThemeReview.PluginTerritory.ForbiddenFunctions.editor_blocks_register_block_type" />
<!-- ページごとのテンプレートを許容 -->
<exclude name="WPThemeReview.Templates.ReservedFileNamePrefix.ReservedTemplatePrefixFound" />
<!-- wp_enqueue_styleでのバージョンnullを許容 -->
<exclude name="WordPress.WP.EnqueuedResourceParameters.MissingVersion" />
<!-- テーマ内でのタクソノミー定義を許容 -->
<exclude name="WPThemeReview.PluginTerritory.ForbiddenFunctions.plugin_territory_register_taxonomy" />
<!-- 無名関数の記述を許容 -->
<exclude name="PHPCompatibility.FunctionDeclarations.NewClosure.ThisFound" />
<!-- 無名関数の記述を許容 -->
<exclude name="PHPCompatibility.FunctionDeclarations.NewClosure.Found" />
<!-- JSON_UNESCAPED_UNICODE定数の利用を許容 -->
<exclude name="PHPCompatibility.Constants.NewConstants.json_unescaped_unicodeFound" />
<!-- テーマファイルでのショートコードを定義を許容 -->
<exclude name="WPThemeReview.PluginTerritory.ForbiddenFunctions.plugin_territory_add_shortcode" />
部分的にルールを適用外にするには下記のようにphpcs:ignore
コメントにて除外することも可能です。
$args = array(
'post_type' => $target_post_type,
'posts_per_page' => $post_per_page,
// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
'meta_query' => array(
array(
'key' =>$target_key,
'value' => get_the_ID(),
'compare' => 'LIKE',
),
),
);
$the_query = new WP_Query( $args );
CI/CD
近年の社内案件では、下記のGitHub Actionを設定しています。
Lint
前述のPHP Parallel LintとPHP_CodeSnifferを実行し、エラーがある場合はPull Requestのマージをブロックします。
name: lint Workflow
on:
pull_request:
branches:
- main
- develop
jobs:
php-lint:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./themes/example_wp_theme_name/
steps:
- uses: actions/checkout@v3
- run: composer install
- run: composer lint:php
- run: composer lint:wpcs
Deploy
name: Deploy to staging
on:
push:
branches:
- develop
jobs:
build-deploy:
runs-on: ubuntu-latest
environment:
name: develop
url: https://example.com
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
- run: npm i
- run: npm run build
- name: Set Commit Hash
id: set_commit_hash
run: echo "::set-output name=hash::${GITHUB_SHA:0:7}"
- name: Update Theme Version
run: |
commit_hash=$(echo ${{ steps.set_commit_hash.outputs.hash }})
sed -i "s/__COMMIT_HASH__/${commit_hash}/" themes/example_wp_theme_name/style.css
- name: rsync deployments
uses: burnett01/[email protected]
with:
switches: -avcz --delete --exclude-from='rsync-exclude.txt'
path: ./themes/example_wp_theme_name/
remote_path: ${{ secrets.DEVELOP_WEB_ROOT }}/wp-content/themes/example_wp_theme_name/
remote_host: ${{ secrets.DEVELOP_HOST }}
remote_port: ${{ secrets.DEVELOP_PORT }}
remote_user: ${{ secrets.DEVELOP_USER_NAME }}
remote_key: ${{ secrets.SSH_SECRET_KEY }}
本番環境へのデプロイも対象ブランチ違いで別途設定します。
キャッシュ対応
このGitHub Actionで特筆すべきはUpdate Theme Version
の箇所です。
WordPressのテーマファイルの修正を反映した際に、ユーザのブラウザキャッシュからCSSやJavaScriptが読み込まれ、レイアウト崩れを発生させることがありますが、開発者が意識しなくても回避できる工夫を入れています。
具体的にはテーマのstyle.css
に定義されるヘッダーコメントセクションのVersion
を下記のようにしています。
/*!
Theme Name: example_wp_theme_name
Theme URI: https://example.com/
Author: add more
Author URI: https://www.add-more.co.jp/
Description: WordPress sample theme
Version: 1.0.__COMMIT_HASH__
Requires PHP: 7.4
Text Domain: addmore
*/
これをsed
コマンドで__COMMIT_HASH__
の部分をそのときのGitコミットハッシュ値に置き換えています。
そうするとバージョン情報は下記のようになります。
Version: 1.0.6af948a
手動でテーマバージョンを変更し忘れたとしても、デプロイの都度、バージョンが必ず変わることを意味します。
function addmore_scripts() {
$theme_data = wp_get_theme();
$theme_ver = $theme_data->get( 'Version' );
wp_enqueue_style( 'addmore-style', get_stylesheet_uri(), array(), $theme_ver );
wp_enqueue_script( 'addmore-common-js', get_template_directory_uri() . '/js/common.js', array( 'jquery' ), $theme_ver, true );
}
add_action( 'wp_enqueue_scripts', 'addmore_scripts' );
例えば、上記例ではデプロイ後に生成されるHTMLとしては下記のようバージョンのクエリパラメータが付加され、以前のテーマから読み込むURLが必ず変化します。
<link rel='stylesheet' id='addmore-style' href='https://example.com/wp-content/themes/example_wp_theme_name/style.css?ver=1.0.6af948a' media='all' />
<script src="https://example.com/wp-content/themes/example_wp_theme_name/js/common.js?ver=1.0.6af948a" id="addmore-common-js"></script>
初期データのセットアップ
5年前はWordMoveなどを用いて、外部サーバーからDBやメディアファイルを取得してローカル環境の整備を行っておりましたが、IaCの観点から近年は初期構築用のコードを記述するケースが多くなってきました。
例えば、npm run setup
を実行すると必要なプラグインのインストールからWordPressの各種設定、シード(初期データ)の登録が行われるような動作にしています。
package.json
package.jsonの抜粋
"scripts": {
"setup": "npx wp-env run cli ../install.sh",
これにより、npm run setup
は.wp-env.json
の設定でDockerインスタンスにマウントしているinstall.sh
を実行することを意味します。
install.sh
install.sh
の抜粋
#!/bin/bash
DEV_USER_EMAIL="[email protected]"
DEV_USER_PASSWORD="PleaseSetPasswordHere"
# プラグインインストール
wp plugin install wordpress-seo --activate
# テーマ有効化
wp theme activate example_wp_theme_name
# 日本語化
wp language core install ja
wp site switch-language ja
wp language plugin install --all ja
# timezone設定
wp option update timezone_string 'Asia/Tokyo'
# 管理者メールアドレス設定
wp option update admin_email $DEV_USER_EMAIL
wp option update new_admin_email $DEV_USER_EMAIL
# 管理者アカウントの情報変更
wp user update admin --user_pass=$DEV_USER_PASSWORD --user_email=$DEV_USER_EMAIL
# 基本設定
wp option update blogname "SAMPLE_WP_SITE"
# コメントやPING受付を停止
wp option update default_comment_status "closed"
wp option update default_ping_status "closed"
wp option update default_pingback_flag 0
# Yoast SEOの設定
wp option patch update wpseo_titles separator "sc-pipe"
# WP-CLI独自コマンドにより初期データのインポート
wp example_wp_theme_name load_init
# パーマリンク設定
wp rewrite structure '/%postname%/'
wp rewrite flush
# 開発関連のインストール
cd wp-content/themes/example_wp_theme_name/ && composer install
プラグインインストール
.wp-env.jsonのpluginsフィールドでプラグインを定義することも可能です。
しかし、この機能を用いてインストールしたプラグインは正常にアップデートできない不具合が生じていたため、弊社ではシェルスクリプトの中でWP-CLIを用いてインストールする手法をとっています。
オプション値の設定
WordPressの設定をwp option
コマンドをつかって記載することで、具体的にどのような設定をすべきかがコードとして定義され、初期セットアップ手順をスクリーンショット付きの手順書をつくる必要がなくなります。
また、一般的なプラグインも設定内容をwp_options
テーブルに保持しており、これらはwp option
コマンドから変更可能です。
たとえばYoastSEOの下記の設定画面でのタイトル区切り文字の変更が可能です。
これはwp option
コマンドを下記のように実行することでも対応可能です。
wp option patch update wpseo_titles separator "sc-pipe"
WP-CLI独自コマンドにより初期データのインポート
WP-CLIのwp post create
などのコマンドを駆使して固定ページや投稿のデータ作成を行うことも可能ではあるのですが、複数のデータが関連する場合、登録後に明確となるIDを用いて関連付けが必要となり、シェルスクリプトで定義するには限界が生じます。
このような複雑な処理が求められるものは、WP-CLIの独自コマンドとして定義すると良いでしょう。
下記はWP_CLI::add_command
にて定義された独自コマンドを呼び出し、その処理の中でメディアアップロードや投稿の作成を行います。
wp example_wp_theme_name load_init
プログラムコード内でデータを定義すると見通しが悪くなるため、JSON形式で定義したり、投稿の本文は外部のテキストファイルとして記載したものを読み込む処理にするのがおすすめです。2
これからの進化
Webサイト制作において、よくある要求や課題は開発支援用のプラグインとして管理し、@wordpress/env
でラップした標準スターターセットとして準備しておくのも良いかと考えています。
株式会社add moreではWordPressサイト制作をより快適に効率よくすすめる環境整備を手伝ってくれるエンジニアを募集しています。
ご興味のある方はコーポレートサイトまたはWantedlyからご応募ください。