Featured image of post BedrockとWpRestaを使ってWordPressで独自のAPIを作成する

BedrockとWpRestaを使ってWordPressで独自のAPIを作成する

Twitter ツイート Hatena Bookmark ブックマーク

WordPressをHeadlessCMSとして使いたいと思い、WordPressが用意しているREST APIではなく、独自のエンドポイントを作りたいと考えました。
通常、独自のエンドポイントを設定する場合は rest_api_initのアクションフックを使用します。

WP REST API を使って独自エンドポイントを設定する。

しかし、もう少し構造化したいと思い、便利そうだと感じたのがWp\Restaでした。
今回はbedrockとWp\Restaを使用してWordPressを設定する手順を書いていきます。

Bedrockでプロジェクトを生成する

公式ドキュメントに従い、 composer create-project でプロジェクトを生成します。

1
$ composer create-project roots/bedrock

Wp\Restaのインストールと設定

Wp\Restaもcomposerでインストールします。

1
$ composer req tenjuu99/Wp\Resta

config/resta.phpファイルを作成して設定を記述する

Wp\Resta用の設定ファイル config/resta.php を作成し、以下の内容を記述します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<?php
$rootDir =  dirname(__DIR__);
return [
  'autoloader' => $rootDir . '/vendor/autoload.php',
  'routeDirectory' => [
    [$rootDir . '/src/Route', 'App\\Route\\', 'custom'],
  ],
  'use-swagger' => true,
  'schemaDirectory' => [
    [$rootDir . '/src/Schema', 'App\\Schema\\'],
  ],
  'dependencies' => [
  ],
];

オートローダーの場所やルーティング用のクラスを配置するディレクトリ、スキーマを配置するディレクトリを指定します。今回はsrc ディレクトリにソースコードを配置します。

Wp\Restaの設定ファイルを読み込ませる。

Wp\Restaは RESTA_CONFIG_FILE という環境変数で設定ファイルの位置を指定できます。 基本的には環境ごとに差異が発生するわけでもないので config/application.phpputenvを使用して設定ファイルのパスを指定します。

1
2
3
4
5
6
// config/application.php

/**
 * resta config
 */
putenv('RESTA_CONFIG_FILE=' . $root_dir .'/config/resta.php');

composer.jsonのオートローダーの設定

src以下を App namespaceとして指定するため、composer.jsonに以下の設定を追記します。

1
2
3
4
5
  "autoload": {
    "psr-4": {
      "App\\": "src/"
    }
  }

実際に独自エンドポイントを定義してみる

以下のようにエンドポイントを定義します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// src/Route/HelloWorld.php
<?php

namespace App\Route;

use Wp\Resta\REST\AbstractRoute;

class HelloWorld extends AbstractRoute
{
    public function callback(): array
    {
        return [
            'message' => 'Hello World!',
        ];
    }
}

この状態でhttpリクエスト送ると「Hello World!」と表示されます。

1
2
$ curl http://localhost/wp-json/custom/helloworld
{"message":"Hello World!"}

URLパラメータの扱いについて

ページ一覧を取得する場合に page のクエリパラメータを受け取るためには、 URL_PARAMS クラス定数に定義します。

よくあるページ一覧みたいなのを取得したい場合に page のクエリパラメータを受け取りたいかと思います。 その場合はURL_PARAMSのクラス定数に定義してあげれば大丈夫です。

定義できるのは string,integerで必須かどうかは先頭に? をつけるかで変わってきます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
final class News extends AbstractRoute
{
    protected const URL_PARAMS = [
        'page' => '?integer',
        'limit' => '?integer',
    ];

    public function callback(int $page = 1, int $limit = 1): array
    {
        $offset = ($page - 1) * $limit;

        $wpQuery = new \WP_Query();
        $posts = $wpQuery->query([
            'post_type' => 'post',
            'post_status' => 'publish',
            'orderby' => 'date',
            'order' => 'DESC',
            'offset' => $offset,
            'posts_per_page' => $limit,
        ]);

        $totalPosts = $wpQuery->found_posts;
        $maxPages = (int)ceil($totalPosts / (int)$wpQuery->query_vars['posts_per_page']);
        return [
            'totalPosts' => $wpQuery->found_posts,
            'totalPages' => $maxPages,
            'posts' => array_map(static function (WP_Post $post) {
                return [
                    'title' => $post->post_title,
                    'content' => apply_filters('the_content', $post->post_content),
                    'date' => $post->post_date,
                ];
            }, $posts),
        ];
    }
}

レスポンスヘッダを定義したい

レスポンスヘッダを追加で定義したい場合は $this->headers で使用します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
final class News extends AbstractRoute
{
    protected const URL_PARAMS = [
        'page' => '?integer',
        'limit' => '?integer',
    ];

    public function callback(int $page = 1, int $limit = 1): array
    {
        $this->headers = [
            'X-POLIDOG-NUMBER' =>  random_int(0, 100000),
        ];

        $offset = ($page - 1) * $limit;

        $wpQuery = new \WP_Query();
        $posts = $wpQuery->query([
            'post_type' => 'post',
            'post_status' => 'publish',
            'orderby' => 'date',
            'order' => 'DESC',
            'offset' => $offset,
            'posts_per_page' => $limit,
        ]);

        $totalPosts = $wpQuery->found_posts;
        $maxPages = (int)ceil($totalPosts / (int)$wpQuery->query_vars['posts_per_page']);
        return [
            'totalPosts' => $wpQuery->found_posts,
            'totalPages' => $maxPages,
            'posts' => array_map(static function (WP_Post $post) {
                return [
                    'title' => $post->post_title,
                    'content' => apply_filters('the_content', $post->post_content),
                    'date' => $post->post_date,
                ];
            }, $posts),
        ];
    }
}

最後に

この構成の良い点は、WordPress、プラグイン、自分たちの拡張がうまく分離できることです。通常はWordPressやプラグインでしか拡張ポイントを作れませんが、自分たちの拡張を src/ 配下に設置できるのはメリットです。

Wp\RestaはWordPress内で使える優れたREST APIフレームワークであり、Bedrockなしでも使える便利なプラグインです。 WordPressで独自のREST APIを作る場合はWp\Restaを使ってみることをおすすめします。

comments powered by Disqus
Built with Hugo
テーマ StackJimmy によって設計されています。