とりあえず動かす方法
投稿を取得したい WordPress のデータベースの設定
一般的に、データベースはセキュリティの観点から限られた接続元からしか接続を受け付けないように設定してあります。例えば、localhost
とか2inc.org
のように自サーバーからの接続しか受け付けませんよ、のように。なので、そのまま外部から投稿を取得しようとしても接続を拒否されてしまうので、まずはデータベースの方で、外部接続用のユーザーを作成し、そのユーザーが WordPress のデータベースを使用できるように設定してください。権限はなるべく少ないほうが良いので、select
だけにしたほうが良いと思います。
レンタルサーバーだとデータベースユーザーが用意されている1つしか使えなかったり、設定の変更ができないことが多いと思いますので RSS をパースしたりするしかないかなと…。
functions.php
/** * switch_blog 用に wp_upload_dir() の返り値を書き換え * 多分 path、basedir も多分必要そうだけど今回は割愛 * * @param array $upload_dir * @return array */ function _habakiri_switch_blog_upload_dir( $upload_dir ) { $pattern = '/^(https?:\/\/[^\/]+)/'; $replacement = home_url(); $upload_dir['url'] = preg_replace( $pattern, $replacement, $upload_dir['url'] ); $upload_dir['baseurl'] = preg_replace( $pattern, $replacement, $upload_dir['baseurl'] ); return $upload_dir; } /** * 別のブログに切り替え */ function habakiri_switch_blog() { global $wpdb, $backup_wpdb; $backup_wpdb = $wpdb; $wpdb = new wpdb( 'データベースユーザー名', 'データベースパスワード', 'データベース名', 'データベースホスト名' ); wp_set_wpdb_vars(); wp_cache_init(); add_filter( 'upload_dir', '_habakiri_switch_blog_upload_dir', 10 ); } /** * 本サイト用に設定を戻す * habakiri_switch_blog した後は必ずこのメソッドでリセットが必要 */ function habakiri_restore_current_site() { global $wpdb, $backup_wpdb; $wpdb = $backup_wpdb; wp_cache_init(); remove_filter( 'upload_dir', '_habakiri_switch_blog_upload_dir', 10 ); }
テンプレート
<?php if ( !empty( $_SERVER['SERVER_ADDR'] ) && $_SERVER['SERVER_ADDR'] === 'ホストのIP' ) : ?> <?php habakiri_switch_blog(); ?> <?php $blog_posts = get_posts( ... ); ?> <?php if ( $blog_posts ) : ?> <?php foreach ( $blog_posts as $post ) : setup_postdata( $post ); ?> <h2><?php the_title(); ?></h2> <?php the_excerpt(); ?> <?php endforeach; wp_reset_postdata(); ?> <?php endif; ?> <?php habakiri_restore_current_site(); ?> <?php endif; ?>
詳しく知りたい方向けに解説
global $wpdb; $wpdb = new wpdb( … ) だけで良いと思っていた時代が私にもありました
投稿データの取得には wp_set_wpdb_vars() が必要
WordPress のデータベース接続を一手に担っている$wpdb
というグローバル変数があります。こいつが全て管理しているならglobal $wpdb; $wpdb = new wpdb( ... )
すればええやん!と思ってやってみたのですが、全然投稿データが取得できませんでした。
なんでかなと実行されている SQL を見てみるとFROM
が空になってる!それじゃ取得できるわけがない…。で、コアのコードを読んでみると、$wpdb = new wpdb( ... )
したあとにテーブル名とかの初期化が必要みたいです。それを行う関数がwp_set_wpdb_vars()
になります。
これで投稿データが取得できるようになります。が…
パーマリンクの取得には wp_cache_init() が必要
タイトルや本文は取得できるのですが、the_permalink()
でパーマリンクを取得すると、なぜかドメインの部分が元サイトのままになっていました。またコアのコードを探ってみると、the_permalink
はオプション値(get_option( 'siteurl' )
)を参照していることがわかりました。WordPress は基本的に、起動時にオプションテーブルのオプション値をドカッと一括で取得してキャッシュするようになっています。なので、このキャッシュ(オプション値)を参照している関数を使用する場合はwp_cache_init()
でキャッシュのリセットが必要になります。
これで正しいパーマリンクが取得できるようになります。が…
アイキャッチの取得には wp_upload_dir() の書き換えが必要
アイキャッチを表示しようとthe_post_thumbnail()
すると、またしてもドメイン部分が元サイトのままになっていました。当然404…。またまたコアのコードを探ってみると、the_post_thumbnail()
はwp_upload_dir()
で upload ディレクトリの URL を取得してそれを使用しているということがわかりました。
wp_upload_dir()
は upload ディレクトリのパスや URL を返す関数ですが、内部では WP_CONTENT_DIR
、WP_CONTENT_URL
のような WordPress の起動時に設定される定数が使用されているため、データベースを切り替えたとしてもこの値は切り替えることができません。そこで、wp_upload_dir()
の返り値を変更するフィルターフックupload_dir
を使って URL 部分を書き換えました。僕のサンプルコードでは、元サイトも取得先ブログのほうもアップロードディレクトリのパスが同じ設定だったので特にパス部分を書き換える処理はいれていませんが、違う場合はそこも書き換えが必要かもしれません。
テンプレート側では必ず接続元のチェックが必要
外部ブログに接続する前には必ず、必ず、接続元のチェックが必要です!これしないと接続エラーで落ちます。
僕のサンプルコードだと<?php if ( !empty( $_SERVER['SERVER_ADDR'] ) && $_SERVER['SERVER_ADDR'] === 'ホストのIP' ) : ?>
として IP でチェックしていますが、ホスト名でも多分大丈夫だと思います。要は、最初に外部ブログのデータベースで接続元の設定をしたと思いますが、それと同じ接続元以外からの接続の場合は$wpdb
の上書きを行わないようにすれば良いということです。
取得が終わったら諸々リセットが必要
$wpdb
やwp_upload_dir()
の返り値を変更しているため、そのままにしていると取得部分のコードより後ろが全て外部ブログのデータを持ってこようとしてしまいおかしなことになってしまいます。なので、取得が終わったら必ず設定のリセットが必要です。僕のサンプルコードでは、habakiri_restore_current_site()
がリセットを行っています。