Steamer Lane Studio技術備忘録WordPress

WordPress サテライトサイトなどで投稿を共有する

wordpress WordPress サテライトサイトなどで投稿を共有する
最終更新日: 2024年6月5日

あるサイトでの投稿のうち特定のカテゴリーに属しまた特定のフィールド(ここではACFを使った)の値が指定の投稿のみを抽出するテンプレートの作成をし、それをサテライトサイトで読み込み成形する。
投稿個別ではなく一覧表示。
個別に拾いつつカテゴリーアーカイブ的なページやsitemapなども作りフルに作るのはマルチサイト化した方が早い。若しくは動的生成ではエンドポイントなど難しいので読み込み元のサイトが静的生成サイトなら可能(過去にMovableTypeサイトでやった)。
SEO的にはコピーコンテンツになるが「同じオーナーであればコンテンツの共有はOK」なので省力化のためにこのコード・スキームを作った。
方法はいくつかあった。最初に別のフィードを作って行ったがオリジナルのfeedへの干渉や読み込みに際しライブラリが要ることなどからテンプレートファイルをエンドポイントとしてアクセスして読み込めるようにした。
読み込む側は普通にphpファイルを読んでそれを成形する形。

function.phpにカスタムエンドポイントを作るコードを記入。

// カスタムエンドポイントの生成function custom_endpoint_init() {add_rewrite_endpoint( 'custom-endpoint', EP_ROOT );}add_action( 'init', 'custom_endpoint_init' );

// カスタムエンドポイント用のコールバック関数function custom_endpoint_callback() {// リクエストがカスタムエンドポイントであるかどうかをチェックglobal $wp_query;if ( isset( $wp_query->query_vars['custom-endpoint'] ) ) {// テンプレートファイルの内容を直接読み込んで出力する$template_file = get_template_directory() . '/ファイル名.php'; // テンプレートファイルのパスを指定if ( file_exists( $template_file ) ) {include $template_file;exit; // 処理を終了} else {// テンプレートファイルが見つからない場合はエラーメッセージを出力echo 'Template file not found.';}}}add_action( 'template_redirect', 'custom_endpoint_callback' );

次にファイル名.phpを作成~テンプレートディレクトリへアップ

<?php/*Template Name: Example Template*/?><?phprequire_once( '/Wordpressのシステムディレクトリのパス・絶対パスが良いかも/wp-load.php' );// WordPress がロードされていることを確認if ( function_exists( 'get_posts' ) ) {$cat_ids = array(13); // カテゴリIDを指定// 投稿タイプを指定$post_type = 'post';// カスタムフィールドキーを指定$meta_key = 'example';// カスタムフィールド値を指定$meta_value = 'ホゲホゲ';//フックとなるカスタムフィールドの値を指定指定// 表示する記事数$item_count = 10;// 記事を取得$args = array('cat_ID' => $cat_ids,'post_type' => $post_type,'meta_key' => $meta_key,'meta_value' => $meta_value,'post_status' => 'publish','order' => 'DESC','orderby' => 'date','posts_per_page' => $item_count,);$posts = get_posts($args);// 取得した記事がない場合は処理を終了if (!$posts) {echo 'No posts found.';exit;}// ページのエンコーディングをUTF-8に指定~サーバーなど各種環境で文字化けするのでheader('Content-Type: text/html; charset=UTF-8');// HTMLのmetaタグでエンコーディングをUTF-8に指定echo '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">';// 記事が存在する場合、ループ処理foreach ($posts as $post) {// タイトルを出力echo '<div><h3>'.html_entity_decode($post->post_title) . "</h3>\n\n";// アイキャッチ画像を出力if (has_post_thumbnail($post->ID)) {$thumbnail_url = get_the_post_thumbnail_url($post->ID);echo '<img src='.$thumbnail_url .' alt="'.$post->post_title.'">';}// コンテンツを出力$content = str_replace(array("\r", "\n", "\t"), "", html_entity_decode($post->post_content));echo '<p>'.$content . "</p></div>";}
//タイトルからコンテンツは適宜変える
} else {echo 'WordPress is not loaded.';//wp-loadを読まないとロードしない、これが出たらwp-loadのパスなどチェック}?>

次に読み込む側のコード

<?php// ターゲットURLを指定$url = "ファイル名のパス.php";// cURLを使用してURLからHTMLデータを取得$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);$html = curl_exec($ch);curl_close($ch);// HTMLをUTF-8にエンコード$html = mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8');// DOMDocumentを作成してHTMLを解析$dom = new DOMDocument();@$dom->loadHTML($html);

// 不要なhtmlタグを削除$body = $dom->getElementsByTagName('body')->item(0);$content = $body->childNodes;$newHtml = '';foreach ($content as $child) {$newHtml .= $dom->saveHTML($child);}

// 生成したHTMLをUTF-8にエンコードして出力~コンバートが重複するので消し込んだがが環境などでエンコード指示を前後変えた方がいいかも//echo mb_convert_encoding($newHtml, 'HTML-ENTITIES', 'UTF-8');echo $newHtml;?>

読み込む側はincディレクトリにおいてショートコードで呼び出すのがベター。

個別の投稿にはならないが、一覧表示で取り込みができる。