CommentOut

WP REST APIで記事取得する時、カスタムフィールドで記事を絞り込む方法 WP REST APIで記事取得する時、カスタムフィールドで記事を絞り込む方法

WP REST APIで記事取得する時、カスタムフィールドで記事を絞り込む方法

公開日:  最終更新日:

マニアックなブログへようこそ。
今回ご紹介するのは、WP REST APIを使って記事一覧を取得する際、取得記事をカスタムフィールドで絞り込む方法です。
WP REST APIの使い方はこちらを参考にしてください。

カスタム投稿タイプとカスタムフィールドを定義

まず、どういうカスタムフィールドを定義するか先に決めておきましょう。
今回は「投稿」ではなく、カスタム投稿タイプ「商品情報」を定義してみます。
functions.phpに以下の内容を記述します。

/*	カスタム投稿タイプの定義
/*---------------------------------------------------------*/
add_action('init', function() {
    //-----------------------------------------
    //	商品情報
    //-----------------------------------------
    register_post_type('products', array(
        'label'			=> '商品情報',
        'public'		=> true,
        'has_archive'	=> true,
        'show_in_rest'	=> true,    // ここがtrueになっていないとWP REST APIで記事を取得できない
        'menu_position' => 5,
        'supports'		=> array(
            'title',
            'editor',
            'thumbnail',
            'revisions',
        ),
        'taxonomies' => array('products-cat')
    ));

    register_taxonomy('products-cat', 'products',
        array(
            'label'			=> 'カテゴリー',
            'hierarchical'	=> true,
            'public'		=> true,
            'show_in_rest'	=> true,
        )
    );
});

そして、以下のようなカスタムフィールドを設定してみました。

これで準備万端です。

WP REST APIでカスタム投稿タイプの記事を取得する

まず、カスタムフィールドを絞り込み条件にする前に、普通にカスタム投稿タイプの記事を取得してみましょう。

REST APIっていうのはURLで情報にアクセスできるAPIです。REST APIで使用するURLをエンドポイントと呼びます。
GETリクエストでURLにアクセスすることで情報を得られるのですが、GETリクエストっていうのは普通にブラウザでアクセスしてもGETリクエスト扱いになるので、ブラウザにURLを入力して取得できるデータを覗いてみましょう。

WordPressでカスタム投稿タイプの記事情報を取得するエンドポイントは以下のフォーマットになります。

https://[サイトURL]/wp-json/wp/v2/[カスタム投稿タイプ名]

例えば、先ほどのカスタム投稿タイプ「商品情報(products)」の場合は以下のようなURLとなります。

https://[サイトURL]/wp-json/wp/v2/products

このエンドポイントをブラウザのURL欄にコピペして、アクセスしてみてください。
うまくいけば、こういう画面が表示されます。

さらにタームで絞り込む場合は以下のようになります。

https://[サイトURL]/wp-json/wp/v2/[カスタム投稿タイプ名]?[タクソノミー名]=[タームID]

こちらも先ほどのカスタム投稿タイプとタクソノミーで作成した場合、以下のようになります。

https://[サイトURL]/wp-json/wp/v2/products?products-cat=11

タームでは絞り込めるけど、カスタムフィールドではちゃんと絞り込めないし、取得した情報にカスタムフィールドを含めることもできないんですよね・・・

WP REST APIでカスタムフィールドを条件にして取得記事を絞り込むには

カスタムフィールド自体プラグインで追加してると思うので、カスタムフィールド自体がWordPressの標準機能ではないんですよね。なので、自分で作る必要があります
今回もfunctions.phpにアクションフックを記述して機能拡張していきます。

今回はrest_api_initアクションフックを活用します。

//-----------------------------------------
// 新しいエンドポイントを定義
//-----------------------------------------
add_action('rest_api_init', function() {
    // 今回は製品紹介の記事一覧を取得するとしましょう。
	register_rest_route('custom-rest/v1', 'products', array(
		'methods'	=> 'GET',
		'callback'	=> 'get_custom_products',
		'args'		=> array(
			'purpose' => array(
				// 未入力時のデフォルト値
				'default' => 'cat01',
				// GETによる入力値のバリデーション
				'validate_callback'	=> function($param, $request, $key) {
					return is_string($param);
				}
			),
		),
	));
});

もう少しソースコードをすっきりさせましょう。

//-----------------------------------------
// 新しいエンドポイントを定義
//-----------------------------------------
add_action('rest_api_init', function() {
    // ~~~~~~
});

これはREST APIを準備する時に呼ばれるフックのようです。
「https://[ドメイン]/wp-json/」にアクセスがあった時に、実行されるんだろうか・・・?

register_rest_route('custom-rest/v1', 'products', array(
    'methods'	=> 'GET',
    'callback'	=> 'get_custom_products',
);

大事なのはこの部分です。
register_rest_routeで、REST APIでアクセスできるURLを定義します。
上記例では、アクセス対象のエンドポイントとしては以下のようになります。

GET https://[サイトURL]/wp-json/custom-rest/v1/products

でも、ここまでだと動きません。
なぜなら、’callback’ => ‘get_custom_products’,の部分のcallback関数 function get_custom_products();を定義していないためです。
なので、次にcallback関数を定義しましょう。

//-----------------------------------------
// 製品紹介用にWP REST APIを改造
//-----------------------------------------
function get_custom_products($data) {
    $posts = get_posts(array(
        'post_type'			=> 'products',
        'posts_per_page'	=> -1,
        'meta_query'		=> array(
            array(
                'key'		=> 'campaign',  	    // カスタムフィールドのキー
                'value'		=> $data['campaign'],   // リクエストから取得した値
				'compare'	=> 'LIKE',			    // 比較条件
            ),
        ),
    ));

	return $posts;
}

//-----------------------------------------
// 新しいエンドポイントを定義
//-----------------------------------------
add_action('rest_api_init', function() {
    // 今回は製品紹介の記事一覧を取得するとしましょう。
	register_rest_route('custom-rest/v1', 'products', array(
		'methods'	=> 'GET',
		'callback'	=> 'get_custom_products',
		'args'		=> array(
			'purpose' => array(
				// 未入力時のデフォルト値
				'default' => 'cat01',
				// GETによる入力値のバリデーション
				'validate_callback'	=> function($param, $request, $key) {
					return is_string($param);
				}
			),
		),
	));
});

気づいたでしょうか?
WP REST APIでエンドポイント経由でアクセスが行われた時、返す記事情報を作っているのは、このcallbackで呼び出された関数内なんです。

// 'callback'	=> 'get_custom_products', // この関数で↓の関数を呼び出している

// 以下の関数はget_postsで記事一覧を取得して、記事一覧をreturnしている
function get_custom_products($data) {
    $posts = get_posts(array(
        'post_type'			=> 'products',
        'posts_per_page'	=> -1,
        'meta_query'		=> array(
            array(
                'key'		=> 'campaign',  	    // カスタムフィールドのキー
                'value'		=> $data['campaign'],   // リクエストから取得した値
				'compare'	=> 'LIKE',			    // 比較条件
            ),
        ),
    ));

	return $posts;
}

上記のget_custom_products関数ですが、引数の$dataの中に、GETリクエストで送られてきた情報が連想配列形式で格納されています
なので、この情報を使って、get_postsで取得する記事情報を絞り込みましょう。

呼び出す時のエンドポイントは以下の通りです。

GET https://[サイトURL]/wp-json/custom-rest/v1/products?campaign=c01

WP REST APIで取得できる情報が足りない

ここまでで、記事の絞り込みは出来たのですが、カスタムフィールドで絞り込んだのだから、取得した記事情報にカスタムフィールドの値を入れて取得したい時もありますよね。
アイキャッチ画像のパスとか、カスタムフィールドの値も取得したいです。

WP REST APIで取得できる値にカスタムフィールドの設定値を含める

//-----------------------------------------
// 製品紹介用にWP REST APIを改造
//-----------------------------------------
function get_custom_products($data) {
    $posts = get_posts(array(
        'post_type'			=> 'products',
        'posts_per_page'	=> -1,
        'meta_query'		=> array(
            array(
                'key'		=> 'campaign',  	    // カスタムフィールドのキー
                'value'		=> $data['campaign'],   // リクエストから取得した値
				'compare'	=> 'LIKE',			    // 比較条件
            ),
        ),
    ));

    // 取得した記事一覧に足りない情報を追加する
	foreach ($posts as $post) {
		// URLを追加
		$post->permalink = get_the_permalink($post->ID);
		// アイキャッチ画像パスを追加
		$post->img_path = has_post_thumbnail($post->ID)? get_the_post_thumbnail_url($post->ID): get_stylesheet_directory_uri().'/images/dummy_img.png';
		// カスタムフィールド
		$post->event_date = get_field('campaign', $post->ID);
	}

	return $posts;
}

こんな感じで、一度get_postsで記事を取得した後、foreachでループさせて、記事IDを元に必要な情報を取得して、$postオブジェクトに足していくことで、REST APIで返されるJSONデータに新しい情報を追加することが可能になります。

宣伝
WordPressサイトのテンプレート編集やトラブル対応、バグ修正、簡単なJavascriptの作成(カルーセルやバリデーション等)など、小規模なスポット対応を受け付けております。
もしお困りごとがありましたら、お問い合わせフォームよりご相談ください。

この記事を書いた人

uilou

uilou

プログラマー

基本的に、自分自身の備忘録のつもりでブログを書いています。 自分と同じ所で詰まった人の助けになれば良いかなと思います。 システムのリファクタリングを得意としており、バックエンド、フロントエンド、アプリケーション、SQLなど幅広い知識と経験があります。 広いだけでなく、知識をもっと深堀りしていきたいですね。