他ブログから記事を取得するブロックの実装|WordPress

仕事用サイトをドメイン直で一つのサイトとして、サブドメインでブログを運用する構成にしているが、最新記事の一覧はドメイン直の方のサイトに出したくて、オリジナルブロックを作成したのでメモ。

RSSブロック

RSSを読み込んで一覧表示するブロックはデフォルトであるので、それで問題なければブロック作成の必要は無し。

その場合は表示内容がRSSに含まれる日付、タイトル、抜粋のみとなる。

画像やカテゴリ名などを表示しようと思ったらこの方法では物足りない。

WP REST-APIを用いたオリジナルブロック

ということでオリジナルのブロックを実装してみる。

管理画面からURLを設定して、該当のURLからWP REST-APIを用いて記事を取得して一覧として表示することを目指す。

雛形作成

まずは雛形を作成。以下は過去の自分で試したときの記事。

出来上がるファイル・フォルダの構成は以下のような感じ。

build

block.jsonなど

node_modules

src

プラグインファイル.php

package.jsonなど

プラグインファイル.php

扱う値の準備

function get_post_list_get_post_list_block_init() {
	register_block_type(
		__DIR__ . '/build',
		array(
			'render_callback' => 'get_post_list_render',
			'attributes' => [
				'blogURL' => [ //記事を取得するブログのURLを扱う変数
					'type' => 'string',
					'default' => ''
				],
				'perPage' => [ //取得する記事数を設定する変数
					'type' => 'number',
					'default' => 0
				],
				'embedCheck' => [ //画像取得のフラグとして使用する変数
					'type' => 'boolean',
					'default' => false
				],
			]
		)
	);
}
add_action( 'init', 'get_post_list_get_post_list_block_init' );

プラグインの処理

function get_post_list_render($attr, $content) { //上記initで指定した関数名と一致させる
	if(!$attr['blogURL']) { //変数の入ったオブジェクト$attrのプロパティblogURlに値が入っているかどうかチェック
		return '記事を取得するURLが入力されていません';
		exit();
	}
	$url = $attr['blogURL'].'/wp-json/wp/v2/posts?context=embed'; //記事のJSON取得のURLを生成
	if($attr['embedCheck'] > 0){ //画像取得のフラグ設定に応じて画像を取得する場合のパラメータを付加
		$url .= '&_embed';
	}
	if($attr['perPage'] > 0){ //記事数をセット
		$url .= '&per_page='.$attr['perPage'];
	}

	$json = @file_get_contents($url); //生成したURLからJSONを取得
	if ($json === false) { //取得できなかった場合
		return '設定されたURLから記事一覧を取得できませんでした';
		exit();
	}

	$arr = json_decode($json,true); //JSONを配列にデコード

	ob_start(); // HTMLとして出力するためのバッファリングを開始
?>

<ul class="wp-block-create-block-get-post-list<?php if(array_key_exists("className",$attr)){echo ' '.$attr["className"];} ?>">
<?php
  foreach ($arr as $data):
    $title = $data["title"]["rendered"];
    $date = date('Y/n/j', strtotime($data["date"]));
    $link = $data["link"];
	$img = "";
	if( $attr['embedCheck'] && array_key_exists("wp:featuredmedia",$data["_embedded"]) ){
		$img = $data["_embedded"]["wp:featuredmedia"][0]["media_details"]["sizes"]["thumbnail"]["source_url"];
	}
?>
	<li class="post-item">
		<time class="post-date"><?php echo $date; ?></time>
<?php if($attr['embedCheck']&&$img!=""): ?>
		<figure class="post-figure">
			<img src="<?php echo $img ?>" alt="">
		</figure>
<?php elseif($attr['embedCheck']&&$img==""): ?>
		<figure class="post-figure">
		</figure>
<?php endif;?>
		<h3 class="post-title">
			<a href="<?php echo $link; ?>" target="__blank" class="post-link"><?php echo $title; ?></a>
		</h3>
	</li>
<?php endforeach; ?>
</ul>
<?php
	if(ob_get_contents()) {
		$output = ob_get_contents(); // バッファの内容(4〜7行目)を $output に取得
		ob_end_clean();  // バッファをクリアしてバッファ制御をオフに
	} else {
		$output = '記事がありません';
	}
	return $output;  //バッファの内容を出力
}

処理の内容はコメントで。

取得したデータは配列として$dataに格納し、HTMLに配置、展開している。

block.json

block.jsonでプラグインの諸々を設定している。

{
	"$schema": "https://schemas.wp.org/trunk/block.json",
	"apiVersion": 2,
	"name": "create-block/get-post-list",
	"version": "0.1.0",
	"title": "Get Post List",
	"category": "text",
	"icon": "smiley",
	"description": "WP REST APIで記事を取得する",
	"supports": {
		"html": false
	},
	"textdomain": "get-post-list",
	"editorScript": "file:./index.js",
	"editorStyle": "file:./index.css",
	"style": "file:./style-index.css"
}

style.scss

この雛形ではeditor.scssで書いた内容はエディターのみ、style.scssに書いた内容は両方に反映されるようにコンパイルされる。

適宜CSSを当てて体裁を整える。

以上でおおよそ動く。

WordPressでも上記URLで値が帰ってこない場合がある。原因は未確認。

WP REST-APIって使っていいの?問題。
以前の知識でWP REST-APIで記事を取得するようにしてみたけど、ググったときに出てくる記事がいずれも2020あたりが最新だったりしてたので、もしかして今はWP REST-APIではやらない?そのあたり把握できていない。