WordPressプラグインの管理をcomposerで行う方法

若干いまさら感はあるのですが、社内向けの技術文書をメンテナンスするより公開ブログにした方が世の中に資するところ多し、と考え、「WordPressプロジェクトをGitHubリポジトリで管理するときにComposerを使うとよい」という趣旨の記事を書きます。

今回の登場人物は「プラグイン」と「Composer」です。

そもそもComposerとは?

Composerとは、PHPのパッケージ管理ツールです。パッケージとは、ある機能の塊を意味します。ライブラリやプラグインなどと読み替えてもらうと理解しやすいかもしれません。要するに、便利な機能をひとまとめにしたものがパッケージなのですが、Composerはこれらパッケージのインストールと依存関係の解決をまとめてやってくれます。

たとえば、あなたがログイン機能を持つシステムをPHPで作ろうとしていて、tarosky/auth という便利なパッケージを見つけたとします。その場合、composerを使って次のように打つと必要なパッケージがインストールされます。

# プロジェクトを開始し、色々入力
composer init
# 必要なライブラリをインストール
composer require tarosky/auth

で、その tarosky/auth ですが、これまた別のパッケージに依存していたとします。ログイン機能なので、データベースアクセスとか、パスワードのハッシュ計算のためのツールとか、クッキーにつけるユニークIDの生成ツールとか、そうしたものですね。意外と多くのものに依存することになるはずです。Comoposerはこれらの「依存しているパッケージがさらに依存しているパッケージ」を勝手に集めてインストールしてくれます。

すべての依存パッケージは、/vendor/vendor-name/package-nameの法則に従ってインストールされます。

vendor
  - taroksy
    - auth # ここに欲しかったパッケージの中身が入る
  - other-vendor
    - db # tarosky/authが依存しているDBライブラリ
    - ....
  - math-master # このベンダーは暗号系が得意なんですかね?
    - password-hash # これも依存ライブラリ。パスワードのハッシュ生成
    - hash-cookie # クッキーになんらかの印をつけるライブラリ
  - ...

この依存関係解決についてユーザーは意識する必要がなく、composerが自動的に判断してくれます。問題がある場合(たとえば、特定のライブラリはPHP8.2以上でしか動かないがあなたの環境は8.1)はインストールのときにエラーが出ます。

まとめると、ComposerというのはPHPの便利ツールを色々いい感じに手配してくれる総合商社のようなものですね。Debian系Linuxならapt、Nodeならnpm、Pythonならpipなど、パッケージ管理ツールはあらゆる環境で利用されています。

Composerの何が便利なの?

さて、そんなComposerですが、本質的な便利さの一つに設定が共有されることがあります。composerでインストールしたパッケージは composer.json として記録されます。

{
    "name": "tarosky/wp-project",
    "require": {
        "php": ">=7.4",
        "tarosky/auth": "^1.0",
    },
    "require-dev": {
        "phpunit/phpunit": "^8|^9",
        "wp-coding-standards/wpcs": "^3.0",
    }
}

これにより、Gitリポジトリで共有しておけば、他の開発者は composer install を打つだけで必要なパッケージがすべてインストールされます。つまり、開発環境のセットアップのためにドキュメントを参考にしてインストールして回る必要がないわけですね。再現性も高く、間違いを起こす可能性も減ります。

ちなみにvendor ディレクトリはリポジトリ管理から除外( .gitignore )して、コードの詳細を関心の対象から外すのが普通です。プラグインがアップデートされるたびに違いがコミットログに残るのは嫌ですからね。

WordPressプラグインはComposerでどうやって取得するの?

ComposerのパッケージはPackagistというリポジトリで配布されていて、これが事実上の標準リポジトリになります。Taroskyが配布しているものもいくつかあります。

では、WordPressプラグインをインストールする方法はあるのかというと、これがなんと……あります!

方法1. WPackagistを使う

WordPress公式ディレクトリのミラーであるWPackagistでは、プラグインとテーマが配布されています。WordPress専用Packagistですね。基本的には wpackagist-plugin/wordpress-seo のような形式で配布されています。

WPackagistのサイト

インストール先のリポジトリを追加するために、composer.json に追記する必要があります。

{
  "repositories": [
    {
      "type": "composer",
      "url": "https://wpackagist.org",
      "only": [
        "wpackagist-plugin/*",
        "wpackagist-theme/*"
      ]
    }
  ]
}

方法2. GitHubなどからダウンロード

Composerはあくまでパッケージ管理ツールなので、パッケージの取得先を指定すれば自分で管理しているパッケージ(例・WordPressプラグイン)も取得できます。複数のプロジェクトにまたがって利用する自前プラグインを管理している方は、以下の方法が便利ですね。

{
  "repositories": [
    {
      "type": "vcs", // ←これを書くと、GitHubなどのURLを指定できる
      "url": "git@github.com:tarosky/my-plugin"
    },
    {
      "type": "package", // Zip配布など
      "package": {
        "name": "tarosky/my-zip-plugin",
        "version": "1.0.0",
        "type": "wordpress-plugin",
        "dist": {
          "url": "https://example.com/tarosky/somewhere-elese/my-zip-plugin.zip",
          "type": "zip"
        }
      }
    }
  ],
  "require": {
    "tarosky/my-plugin": "dev-main", // mainブランチにあるものを使う
    "tarosky/my-zip-plugin": "1.0.0", // 上で指定したもの
  }
}

※JSONにコメント書いちゃいけないのですが、説明のため書いておきます。

  • repositories というパラメータで取得先を追加できます。GitHubやzip配布など
  • Gitのプライベートリポジトリであっても、sshで書いておけば、composer install を実行する人に権限があるかどうかでインストール可否が決まるので安心です。
  • 配布する側のプラグインにも composer.json をおいておき、type: wordpress-plugin としておくと安心です。

プレミアム・プラグインをどうする?

難しいのはプレミアムプラグインですね。Gravity FormsやAdavanced Custom Fields Proなど多くのプレミアム・プラグインはGitHubなどで配布していません。GPLライセンスであれば、少なくともチーム内で共有することにまったく問題はないのですが、composer管理するのが面倒です。

方法としては以下のアイデアが考えられます。プラグインの利用頻度など含めてチームで共通認識を作っておくとよいでしょう。

  1. ソースコードが汚染されてもいいからGitリポジトリにまるごと含めてしまう(例・wp-content/plugins/some-premium-plugin )。プラグインが更新されるたびにGitリポジトリに巨大なコミットログが残るのがデメリット。
  2. プレミアムプラグインはzipに固めてリポジトリ共有し、composer install のときについでに解凍されるようにする(some-plugin.zipはgit管理し、some-pluginディレクトリはignoreする)。バイナリファイルなのでGit差分は汚染されない。
  3. 面倒だが、プレミアム・プラグイン共有用のリポジトリを作る。この共有用リポジトリをメンテナンスする、という手間が発生する。

私のおすすめの方法は2です。

プラグインのインストール場所を指定する

さて、composerでインストールしたパッケージは通常 composer.json のあるディレクトリの vendor 配下にインストールされます。しかし、composer.json  に以下のように書いておくと、別のディレクトリにインストールされます。たとえば、 wp-content相当をGitHubリポジトリとして管理している場合……

{
  "extra": {
    "installer-paths": {
      "plugins/{$name}": [
        "type:wordpress-plugin" 
      ]
    }
  }
}

wpackagist.orgの記載通りに書くと、wordpress-pluginと認定されるパッケージはpluginsディレクトリにインストールされます。もしWordPressルートをGitで管理しているなら、wp-content/plugins/{$name} と書けばオッケー。

プラグインの依存レベルを分ける

さて、オリジナルテーマなどで作っている場合、依存関係もcomposer.jsonに反映したいところですよね。よくあるパターンとしてはACFやWooCommerceですが、こうした「どう考えてもサイトを動かすためになくてはならないプラグイン」に関しては require に、wp cron managerやQuery monitorのような「サイト運営に必須ではないが開発の時はあると便利なプラグイン」は require-dev に指定するとよいでしょう。

ふりかえり・なんでWordPressプラグインをComopserで管理するの?

WordPressには管理画面でプラグインをインストールする機能があるのになんでこんなめんどくさいことをするのでしょうか。それは次の観点が大きいです。

  • プロジェクト設定の共有ができる
  • プロジェクト設定の変更履歴が残る
  • プロジェクト設定に再現性がある

管理画面でぽちぽち操作するよりもコードで管理した方が間違いが少ない、と思う局面はエンタープライズWordPress運用保守で特に多いです。実際、Roots.ioという「WordPress開発のテンプレートを開発するコミュニティ」があるのですが、そこでもComposerを使った管理(Bedrock)が推奨されています。

PhpStormなどの統合開発環境によるメリット(プロジェクト内にあるファイルを参照してコードヒントをくれる)は以前からありましたが、Claude codeやCLINEなどのIDEと統合された生成AIもプロジェクト内のファイルを読み取って思考するので、「composer.jsonがあるということはそれに依存先が書いてあるのだろう」と判断してくれるはずです。また、CodeQL(GitHubのセキュリティ機能)やSnyk(脆弱性診断ツール)はpackage.jsonやcomposer.jsonを読み取って脆弱性診断をしてくれるので、これまたメリットしかありません。今後もこの傾向は増していくはずで、マシン・リーダブルなプロジェクトの方が色々と得をすることが増えていくでしょう。

まとめると、composerで管理するのはWordPressの管理画面からプラグインをインストールするよりめんどくさいがメリットの方が大きい、です。それでは、よいWordPress開発生活をお送りください。