WordPressプラグイン開発：Composerでパッケージをインストールする方法

ハイサイ！オースティンやいびーん！

# 概要

WordPressのプラグインでComposerを設定してパッケージをインストールする方法を紹介します！

その過程で、Composerのオートーローダーも一緒にセットアップします。

## 背景

こないだ、GoogleでWPユーザーの認証を行えるプラグインを開発していました。Googleでログインする上、古いユーザーのデータベースからデータを移行する機能も必要でした。

それで、独自で認証プラグインを開発することになったのですが、GoogleのPHP APIが必要になってくるのがわかります。そのAPIは、通常、Composerでバージョン管理をしますが、WordPressのプラグインでComposerを使うやり方は明確ではありません。

本記事では筆者が考えた解決法を紹介します！

# プラグインのSubModuleをセットアップする

お使いのWordPressアプリケーションの`wp-content/plugins`フォルダーに新しいフォルダーを追加します。

そこに、プラグインのメーンファイルに[ヘッダー](https://developer.wordpress.org/plugins/plugin-basics/header-requirements/)を追加します。メーンファイルのファイル名とフォルダー名を同一のkebab-caseの名前に統一してください。

```php:wp-content/plugins/am-oauth-plugin/am-oauth-plugin.php
<?php

/**
 * Plugin Name:       OAuth Plugin
 * Description:       A plugin which allows third party OAuth in WordPress
 * Requires at least: 6.2
 * Requires PHP:      8.0.0
 * Version:           0.0.0
 * Author:            Austin J. Mayer
 * License:           MIT
 * Text Domain:       am-oauth-plugin
 */
```

zshで同フォルダー内に入って以下のコマンドを実行します。

```
git init
git add -A
git commit -m "init commit"
git remote set-url origin https://github.com/your/repo
git push origin master
```

これで別のレポジトリーとしてこのプラグインのソースコードをバージョン管理できますが、親のレポジトリーに[サブモジュール](https://git-scm.com/book/ja/v2/Git-%E3%81%AE%E3%81%95%E3%81%BE%E3%81%96%E3%81%BE%E3%81%AA%E3%83%84%E3%83%BC%E3%83%AB-%E3%82%B5%E3%83%96%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB#r_git_submodules)として登録しないといけません。

筆者のプロジェクトの場合は以下のようにレポジトリーURLと上書きしたいパスを入れました。

```
cd <レポジトリーのルートフォルダー>
git submodule add https://github.com/tronicboy1/am-oauth-plugin.git ./src/plugins/am-oauth-plugin
```

こうするとサブモジュールとして機能しています！

# Composerをセットアップ

ここからはcomposerを使います。Composerを初めてお使いの方に説明しますが、ComposerはPHPのパッケージをインストールしたり、そのバージョンを管理したりしてくれるソフトウェアです。JavaScriptで言うとNPM、PythonだとPIPに相当するものです。

composerのCLIをインストールする必要があるので、まだの方は[Homebrew](https://brew.sh/index_ja)でインストールすることをお勧めします。[Composerのドキュメント](https://getcomposer.org/doc/00-intro.md#installation-linux-unix-macos)でもインストール方法が書いてあります。

```
brew install composer
```

そこから、もう一度プラグインのフォルダーに戻ってzshで以下のコマンドを実行します。

```
composer init
```

CLIのプロンプトに従って問われる項目を記入していきます。パッケージは今インストールしなくていいです。`autoloader`のパスを問われますが、デフォルト値の`src`で大丈夫です。

終わると以下のように`composer.json`が追加されます。

```json:composer.json
{
    "name": "tronicboy1/am-oauth-plugin",
    "description": "A plugin which allows third party OAuth in WordPress",
    "type": "library",
    "license": "MIT",
    "autoload": {
        "psr-4": {
            "Tronicboy1\\AmOauthPlugin\\": "src/"
        }
    },
    "authors": [
        {
            "name": "Austin John Mayer (井上 オースティン)",
            "email": "mayeraus41@gmail.com"
        }
    ],
    "require": {}
}
```

`autoload`の項目に注目してほしいです。`psr-4`という自動読み込み方策になっていますが、これは`src`フォルダー内に入っているCamelCase.phpのPHPファイルを読み込んで`Tronicboy1\AmOauthPlugin`という[namespace・名前空間](https://www.php.net/manual/ja/language.namespaces.rationale.php)で使えるようにするものです。これによって`require_once`を各ファイルにて記述する必要がなくなります。

CamelCase.phpのようなファイルには、同名のクラスを定義する必要があります。そのクラスが別のnamespaceと同じnamespaceで使えるようになります。

試しに必要なファイルを追加してみましょう。最初に`am-oauth-plugin.php`に`namespace`とオートロードの`require`を追加しましょう。

```php:am-oauth-plugin.php
<?php

/**
 * Plugin Name:       OAuth Plugin
 * Description:       A plugin which allows third party OAuth in WordPress
 * Requires at least: 6.2
 * Requires PHP:      8.0.0
 * Version:           0.0.0
 * Author:            Austin J. Mayer
 * License:           MIT
 * Text Domain:       am-oauth-plugin
 */

 namespace Tronicboy1\AmOauthPlugin;

 require 'vendor/autoload.php';
```

それから`src`にGoogle認証に必要なファイルを作ります。

### ユーザー工場

```php:src/UserFactory.php
<?php

namespace Tronicboy1\AmOauthPlugin;

use Exception;
use WP_User;

class UserFactory
{
  public function create(string $email, string $password = ''): int
  {
    $user = new WP_User();
    $user->user_email = $email;
    $user->user_login = $email;

    $user_id = wp_insert_user($user);

    if (!is_int($user_id)) {
      throw new Exception('UserNotCreated');
    }

    return $user_id;
  }
}
```

### REST APIのコントローラー

```php:src/Controller.php
<?php

namespace Tronicboy1\AmOauthPlugin;

use WP_REST_Request;
use WP_REST_Response;

class Controller
{
  static function init(): void
  {
    register_rest_route('am-oauth/v1', '/google', [
      'methods' => 'POST',
      'callback' => 'Tronicboy1\AmOauthPlugin\Controller::google',
      'permission_callback' => function () {
        return true;
      }
    ]);
  }

  static function google(WP_REST_Request $request): WP_REST_Response
  {
    $body = $request->get_json_params();
    $text = $body['credential'];
    if (!$text) {
      return Controller::make400Response('InvalidBody');
    }

    $factory = new UserFactory();

    return Controller::make200Response();
  }

  static private function make400Response($message = ''): WP_REST_Response
  {
    $response = new WP_REST_Response($message);
    $response->set_status(400);
    return $response;
  }

  static private function make200Response($data = 200): WP_REST_Response
  {
    $response = new WP_REST_Response($data);
    $response->set_status(200);
    return $response;
  }
}
```

そして、プラグインメーンファイルの`am-oauth-plugin.php`に以下の一行を追加すると、オートーローダーのおかげでうまくいくはずです。

```php
 add_action('rest_api_init', __NAMESPACE__ . '\Controller::init');
```

プラグイン管理画面でこのプラグインを有効にして、WP APIを試してみましょう！

![Screenshot 2023-05-20 at 7.47.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344956/aba2300d-3e33-f9ad-b4e2-8c4c343b5576.png)

ブラウザで以下のJavaScriptをコンソールで実行してみれば、うまく起動していることが確認できます。

```javascript
fetch('http://localhost:8080/wp-json/am-oauth/v1/google', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json'
    },
    body: JSON.stringify({ credential: 'test' })
}).then(console.log);
```

![Screenshot 2023-05-20 at 7.51.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344956/eaa08f04-ad3f-066e-c018-2cb5711be830.png)


# Googleのパッケージをインストールする

ここまでの説明でComposerが使えるようにできました。自分のソースコードを自動的に読みこむという目当てだけでも使いたくなる、便利なComposerですね。

しかし、本当の目的は第三者パッケージをインストールすることなので、それをしましょう！

以下のコマンドを実行します。

```
composer require google/apiclient
```

実行すると、Google PHP APIとそれを実行するために必要になるパッケージをインストールしてくれます。そして`composer.lock`を作成して、それぞれのパッケージが相性良くインストールできた状態が別の環境でも再現できるように記録を残してくれるのです。

これをインストールした上でもう一度`src/Controller.php`に戻ってGoogleのパッケージを使ってみましょう。

環境変数に僕のAPIコードを設定していますが、とりあえずベタ書きで問題ありません（本番は環境変数に！）。

```php:src/Controller.php
use Google_Client;

...

  static function google(WP_REST_Request $request): WP_REST_Response
  {
    $body = $request->get_json_params();
    $credential = $body['credential'];
    if (!$credential) {
      return Controller::make400Response('InvalidBody');
    }

    $client = new Google_Client(['client_id' => getenv('GOOGLE_CLIENT_ID')]);

    $factory = new UserFactory();

    return Controller::make200Response();
  }
```

これで試してみるとうまくい... あ！エラーが発生！

```
PHP Fatal error:  Composer detected issues in your platform: Your Composer dependencies require a PHP version ">= 8.1.0". You are running 8.0.28.
```

`composer.json`の設定が間違っていましたので、以下のように`config`を追加してPHPのバージョンを設定しましょう。

```json:composer.json
{
  "name": "tronicboy1/am-oauth-plugin",
  "description": "A plugin which allows third party OAuth in WordPress",
  "type": "library",
  "license": "MIT",
  "autoload": {
    "psr-4": {
      "Tronicboy1\\AmOauthPlugin\\": "src/"
    }
  },
  "authors": [
    {
      "name": "Austin John Mayer (井上 オースティン)",
      "email": "mayeraus41@gmail.com"
    }
  ],
  "require": {
    "google/apiclient": "^2.15"
  },
  "config": {
    "platform": {
        "php": "8.0.0"
    }
  }
}
```

`composer.lock`を直す必要があるので以下のコマンドも実行します。

```
composer update 
```

そうすると、200番が返ってきます。

![Screenshot 2023-05-20 at 8.09.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344956/2daa74be-e364-1825-a0e1-1926bdd0fb1a.png)

このあとはGoogleの認証を実装して、フロントエンドでログインできるブロックを実装しますが、それは本記事とは別の課題ですのでここまで！

# まとめ

WordPressのプラグインでComposerを使う方法を紹介しましたが、いかがでしょうか？

WordPressは古く、今だと独特極まりない開発環境になりますが、それでも今も**もっとも強いCMSであることは変わりないです**。うまく付き合っていくしかない。今回の記事はその延長線で考案したものです。

しかし、ComposerのようなモダンなツールとWordPressとの間には相入れない部分があります。

例えば、上記のコードでは`vendors`をローカルでインストールしているのですが、プラグインとしてインストールする場合、`composer install`を実行するわけにはいかないでしょう。

そうなるとどうしたらいいかというと、プラグインとしてバンドルしてリリースする必要があります。

そのやり方もまた別の記事でいずれ書くかもしれません。

とりあえず、WordPressでもComposerが使えるのは非常にありがたいので共有しました！