0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

WordPressプラグインを公開品質まで仕上げる ― Composer依存関係とPlugin Checkで考えたこと

0
Last updated at Posted at 2026-08-19

はじめに

前回、WordPressからAmazon S3を利用する際に、長期Access KeyをWordPressへ保存せず、IAM RoleとAWS SDKのCredential Provider Chainを利用する方法について書きました。

その考え方を実際に試すため、WordPressのデータベースをS3へバックアップするプラグインを作成しました。

実装そのものは比較的順調に進みました。

しかし、WordPress.orgへの公開を意識し始めると、単に「動く」だけでは足りませんでした。

特に大きかったのが、次の二つです。

Composerで導入したAWS SDKをどう安全に同梱するか
WordPress Plugin Checkの指摘をどこまで受け入れるべきか

最終的にはPlugin Checkでエラー0件まで持っていきましたが、その過程で、

警告を消すことと、正しい設計にすることは必ずしも同じではない

と感じる場面が何度もありました。

今回は、その過程を整理してみます。

1. ComposerでAWS SDKを入れるだけでは終わらない

AWS SDK for PHPはComposerから簡単に導入できます。

composer require aws/aws-sdk-php

WordPressプラグイン側では、

use Aws\S3\S3Client;


$client = new S3Client([
    'version' => 'latest',
    'region'  => $region,
]);

のように利用できます。

ここまでは普通のPHPアプリケーションと同じです。

問題は、WordPressでは複数のプラグインが同じPHPプロセス上で動く ことです。

自分のプラグインが、

aws/aws-sdk-php 3.x
guzzlehttp/guzzle 8.x

を読み込んでいても、別のプラグインが異なるバージョンのAWS SDKやGuzzleを読み込んでいる可能性があります。

それぞれがComposerのautoloadを登録すると、どちらのクラスが先に読み込まれるかによって、想定していないライブラリが使われる可能性があります。

つまり、

Plugin A
 └─ Aws\S3\S3Client


Plugin B
 └─ Aws\S3\S3Client

という状態では、namespaceが同じです。

Composerを使ったから依存関係の問題が解決するわけではなく、

WordPressという一つのPHP実行環境に、複数のComposer環境が共存する

という別の問題が出てきます。

2. PHP-Scoperで依存ライブラリを隔離する

そこでPHP-Scoperを使うことにしました。

PHP-Scoperは、PHPのnamespaceにprefixを付けることで、依存ライブラリを他のコードから分離できます。

例えば本来、

Aws\S3\S3Client

だったクラスを、

SecureS3StorageForWordpressVendor\Aws\S3\S3Client

のように変換します。

こうすると、

他プラグイン
Aws\S3\S3Client


自分のプラグイン
SecureS3StorageForWordpressVendor\Aws\S3\S3Client

となり、衝突を避けやすくなります。

今回のリリースビルドでは、おおまかに次の処理を行っています。

composer install --no-dev
        ↓
PHP-Scoper
        ↓
namespaceをprefix
        ↓
autoload再生成
        ↓
ZIP作成

この処理を手作業にするとミスが起きやすいため、build-release.sh として自動化しました。

最終的な配布ZIPだけを成果物とし、開発用ファイルやテストコードは含めません。

3. 「ソースコード」ではなく「配布ZIP」をチェックする

これはPlugin CheckをGitHub Actionsへ組み込む過程で改めて気づいたことです。

最初はGitHubリポジトリ全体をPlugin Checkへ渡しました。

すると、

tests/
.github/
.gitignore
build-release.sh

といった、実際にはWordPressへ配布しないファイルまで検査されました。

当然、大量の警告やエラーが出ます。

しかし、WordPress.orgへ配布するのはGitリポジトリそのものではありません。

配布するのは、

secure-s3-storage-0.1.0.zip

です。

そこでCIを、

GitHub checkout
    ↓
build-release.sh
    ↓
release ZIP
    ↓
ZIPを展開
    ↓
Plugin Check

という構成に変更しました。

つまり、

実際に利用者へ配るものを検査する

という考え方です。

最終的にはGitHub Actions上で、

Success: Checks complete. No errors found.

まで確認できました。

4. Plugin Checkの警告はすべて直すべきか

Plugin Checkを実行すると、WordPressらしいコードになっているかをかなり細かく確認してくれます。

例えば、

output escaping
text domain
prefix
direct database access
filesystem access
prohibited functions

などです。

多くの指摘は、そのまま修正すべきものでした。

一方で、判断が必要なものもありました。

今回その代表だったのが、

unlink()
fopen()
fread()
fwrite()
fclose()
chmod()
proc_open()
mysqli_report()

などです。

Plugin CheckやWordPress Coding Standardsでは、これらに対して警告が出る場合があります。

最初に考えたのは、

WordPress APIにすべて置き換えるべきなのか

ということでした。

しかし一つずつ確認すると、そう単純ではありませんでした。

5. ストリーミング処理とWP_Filesystem

データベースdumpは、場合によっては数GBになる可能性があります。

そのため、

$handle = fopen($path, 'wb');


foreach ($rows as $row) {
    fwrite($handle, $sql);
}


fclose($handle);

のように、少しずつ書き込む方式を採用しています。

gzip圧縮も同じです。

SQL dump
   ↓
一定サイズずつread
   ↓
gzipへwrite

としています。

もし「WordPressらしくする」ことだけを目的に、この処理を無理に別のAPIへ置き換えると、メモリ上に大きなデータを保持する設計になってしまう可能性があります。

バックアップ処理では、

メモリ消費を抑えてストリーミングする

ことの方が重要です。

そこで、このような箇所では理由を確認した上で、局所的にPHPCSの抑制コメントを付けることにしました。

6. proc_open()を使う理由

データベースdumpでは、可能であれば、

mysqldump
mariadb-dump

を使用しています。

そのため外部プロセスを起動する必要があり、proc_open()を使っています。

ただし、

mysqldump -u user -ppassword ...

のようにパスワードをコマンドラインへ直接渡すことはしていません。

一時的なMySQL option fileを作り、

chmod 0600

で権限を制限してから利用します。

また、proc_open()が利用できない環境では、PHPだけでSQL dumpを生成するfallbackも実装しています。

つまり、

native dump
     ↓
使えない
     ↓
PHP fallback

という構成です。

この場合、

proc_open()が警告されているから削除する

という判断ではなく、

なぜ使っているのか、リスクはどう抑えているのか

を確認する必要があります。

7. 警告ゼロが目的になると設計を壊すことがある

Plugin Checkは非常に有用でした。

実際、今回も数多くの問題を見つけてもらいました。

ただし、最終的に感じたのは、

静的解析ツールは設計判断を代わりにしてくれるものではない

ということです。

例えば、

unlink() が警告された
        ↓
無条件で別の関数へ置換する

ではなく、

なぜunlink()を使っているのか
        ↓
一時ファイルなのか
        ↓
WordPress管理下のファイルなのか
        ↓
置換すると処理特性が変わらないか
        ↓
リスクを理解した上で判断する

という順番が必要です。

結果として警告0件になったとしても、

0件にするためにコードを書いた

のではなく、

一つずつ判断した結果として0件になった

という違いは大きいと思います。

8. GitHub Actionsで自動化する

最終的にはPlugin CheckをGitHub Actionsへ組み込みました。

概念的には、

- checkout
- PHP setup
- release build
- release ZIP extract
- wordpress/plugin-check-action

という構成です。

これによって、今後コードを変更してpushするたびに、

release ZIP生成
        ↓
Plugin Check

を自動的に実行できます。

ローカルPCの環境やWordPress管理画面の状態に依存しません。

特に今回、Plugin Checkの管理画面にAIコードレビュー機能が追加されていたこともあり、

決定論的な静的チェックはCI側へ持っていく

方が扱いやすいと感じました。

AIレビューを使うこと自体は有用ですが、静的解析とは役割を分けて考えたいと思います。

9. Plugin Checkで0件でも、WordPress.orgのレビューは終わりではなかった

GitHub Actions上でPlugin Checkを実行し、

Success: Checks complete. No errors found.

まで確認できたため、WordPress.orgへの登録申請を行いました。

しかし、申請後のレビューではPlugin Checkとは異なる観点からいくつか指摘を受けました。

その結果、最初の公開候補だった 0.1.0 から 0.1.1 へ修正しています。

主な変更は次の通りです。

Secure S3 Storage
        ↓
Ozeki Database Backup for S3

プラグイン名については、S3 という名称の扱いや、他のプラグインと区別できる名前であることを考慮し、より明確で固有性のある名前へ変更しました。

また、Retentionについても見直しました。

当初は管理画面で、

7
14
30

の3種類から保持世代数を選ぶ方式にしていました。

内部の実装自体は任意の保持数を扱えるようになっていましたが、UI側でこの3種類だけに制限していました。

WordPress.orgのレビューでは、これは「内部的には利用可能な機能を意図的に制限している」と解釈される可能性があることを知りました。

そこで、

任意の正の整数

を保持数として指定できるように変更しました。

さらに、PHPによるdatabase dump fallbackではWordPress本体が利用しているDB接続とは別に mysqli 接続を作成しています。

これは外部から任意のDB接続情報を受け取るためではなく、

WordPress shared DB connection
        ↓
通常処理


PHP dump fallback
        ↓
専用mysqli connection
        ↓
consistent snapshot transaction

というように、バックアップ用transactionをWordPress本体の共有DB接続から分離するためです。

この点についても、コードだけでは意図が伝わりにくいため、説明を明確にしました。

このレビュー対応を行った 0.1.1 では、あわせてDaily Cronの初回設定時の登録処理も修正しています。

今回ここで改めて感じたのは、

Plugin Checkでエラー0件になることと、WordPress.orgの公開要件をすべて満たしていることは同じではない

ということです。

Plugin Checkは主にコードやWordPressのベストプラクティスを機械的に確認してくれます。

一方、WordPress.orgのレビューでは、

名称・商標
機能制限
配布方針
ユーザーへの説明
コードの意図

といった、より広い観点から確認されます。

静的解析を通した後に、人間やレビューシステムから別の視点で確認してもらう意味は大きいと感じました。

まとめ

今回、WordPressプラグインをWordPress.orgへ申請できる状態まで仕上げ、そのレビュー対応を進める中で、

Composer
PHP-Scoper
Release build
Plugin Check
GitHub Actions

まで扱うことになりました。

その中で最も印象に残ったのは、

ツールの指摘に従うことと、正しい設計をすることは同じではない

ということです。

Composerを使えば依存関係がすべて解決するわけではありません。

Plugin Checkを通せば自動的に良い設計になるわけでもありません。

それぞれのツールが何を守ろうとしているのかを理解しながら、自分のコードでなぜその実装が必要なのかを判断することが重要だと感じました。

今回作成したプラグインのソースコードとリリースビルドの仕組みはGitHubで公開しています。

WordPress.orgへの登録申請後、レビューで指摘された内容を反映し、現在は0.1.1として再提出しています。

(GitHub URL)

Ozeki Database Backup for S3 - GitHub

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?