別のWordPressサイトの投稿を取得して自分のサイトに表示したいとき、REST API(/wp-json/wp/v2/posts)を使うのが基本です。サーバー側で wp_remote_get() を使い、安全な出力とキャッシュまで含めて実装するのが実用的です。
この記事でわかること
- REST APIのエンドポイントと
wp_remote_get()での取得 content.renderedを安全に出力する(二重エスケープを避ける)- トランジェントでキャッシュして毎回叩かないようにする
- タイムアウト・取得件数の指定
REST APIは「有効化」不要(デフォルトで有効)
REST APIはWordPress 4.7以降、標準で有効です。「設定 → パーマリンク」で有効化する、といった操作は不要で、そのような設定項目もありません。対象サイトのエンドポイント(
REST APIはWordPress 4.7以降、標準で有効です。「設定 → パーマリンク」で有効化する、といった操作は不要で、そのような設定項目もありません。対象サイトのエンドポイント(
https://example.com/wp-json/wp/v2/posts)にアクセスしてJSONが返れば利用できます(セキュリティプラグインでREST APIを制限しているサイトは取得できないことがあります)。REST APIで投稿を取得して表示する
テーマの functions.php やテンプレートで、wp_remote_get() を使って取得します。件数(per_page)とタイムアウトを指定し、is_wp_error() でエラーを確認します。
PHP:外部サイトの投稿を取得して表示
$api_url = 'https://example.com/wp-json/wp/v2/posts?per_page=5'; // 件数を指定
$response = wp_remote_get($api_url, array(
'timeout' => 10, // 外部が遅いとき固まらないように
));
if (is_wp_error($response)) {
echo '<p>記事を取得できませんでした。</p>';
} else {
$posts = json_decode(wp_remote_retrieve_body($response));
foreach ((array) $posts as $post) {
echo '<h3><a href="' . esc_url($post->link) . '">'
. esc_html($post->title->rendered) . '</a></h3>';
// content.rendered は整形済みHTML → esc_html ではなく wp_kses_post
echo '<div>' . wp_kses_post($post->content->rendered) . '</div>';
}
}
本文は esc_html ではなく wp_kses_post で出す
REST APIの
REST APIの
content.rendered・title.rendered はすでにHTMLとして整形済みです。本文を esc_html() で囲むと <p> などのタグが文字としてそのまま表示され、本文が壊れます(wpautop も不要)。本文は許可タグだけ通す wp_kses_post()、タイトル文字は esc_html()、リンクは esc_url() と使い分けてください。トランジェントでキャッシュする(実用上ほぼ必須)
外部APIをページ表示のたびに毎回叩くと、表示が遅くなり相手サーバーにも負担をかけます。トランジェント(set_transient / get_transient)で一定時間キャッシュしましょう。次の例は1時間キャッシュします。
PHP:取得結果を1時間キャッシュする
function get_external_posts() {
$cache_key = 'external_posts';
$cached = get_transient($cache_key);
if ($cached !== false) {
return $cached; // キャッシュを返す
}
$response = wp_remote_get('https://example.com/wp-json/wp/v2/posts?per_page=5', array(
'timeout' => 10,
));
if (is_wp_error($response)) {
return array();
}
$posts = json_decode(wp_remote_retrieve_body($response));
set_transient($cache_key, $posts, HOUR_IN_SECONDS); // 1時間キャッシュ
return $posts;
}
あとは get_external_posts() でループするだけです。サイト全体の表示速度対策はWordPressサイトを高速化する7つのステップも参考になります。
クリック時に読み込む場合(Ajax)
「ボタンを押したら読み込む」「無限スクロールで追加する」など非同期で取得したい場合はJavaScript(fetch/Ajax)を使います。ただしブラウザから外部サイトのAPIを直接叩くとCORSで弾かれることがあるため、自サイトのPHP(上記)を経由して中継するのが確実です。Ajaxの基本はAjaxを使用する方法、スクロールでの追加読み込みはAjaxを使った無限スクロールを実現する方法を参照してください。
よくある質問(FAQ)
Q取得した本文にHTMLタグが文字で表示されてしまいます。
A
content.rendered は整形済みHTMLなので、esc_html() で囲むとタグが文字として表示されます。本文は wp_kses_post() で許可タグだけ通して出力してください。wpautop() も基本は不要です。Q取得に失敗する・表示が固まる場合は?
A
is_wp_error() でエラーを確認し、wp_remote_get() の第2引数にarray('timeout' => 10) を渡してタイムアウトを調整します。毎回APIを叩かないようトランジェントでキャッシュすると安定します。対象サイトがREST APIを制限している場合は取得できません。QRSSフィードから取得する方法もありますか?
Aあります。
fetch_feed('https://example.com/feed/') でフィードを取得し、$feed->get_items(0, 5) でループします。タイトルとリンクだけ表示したい軽い用途に向いています。RSSの投稿者名を隠す設定はRSSフィードの投稿者名を非表示にする方法を参照してください。まとめ
- 取得:
wp_remote_get()(per_page・timeout指定)+is_wp_error() - 出力:本文は
wp_kses_post()、タイトルはesc_html()、リンクはesc_url() - キャッシュ:
set_transient/get_transientで毎回叩かない - 前提:REST APIはデフォルト有効(有効化操作は不要)
「安全な出力」と「キャッシュ」の2点を押さえれば、外部サイトの投稿を速く・崩さず表示できます。
