こんにちは、ニタです。
早速ですが、WordPressのプラグインを更新しました!
アイキャッチ画像と更新日を予約更新対象に追加しました!
iframeタグが消えたり、brタグなどに追記したstyle定義も消えないようにしました!
予約更新内容でのプレビュー機能はもう少し先になりそうです!
どうぞよろしくお願いします!
See you again next time, Enjoy WordPress Life!!
と、
これでおしまいとは、いきませんよねぇ…。
では、改めて。
WordPressでもajaxをカンタンに使いたい
WordPressのテーマやプラグインを開発していると、投稿データや外部からのデータをスムーズに取得したい時があります。なるべくスマートに。ajaxとかで。
例えば、投稿一覧ページをページングからajax読み込みによる無限スクロールにしてみたり、プラグインで下のような読み込み機能に使ってみたり…
多少コツが要ります
しかし、WordPressのフロント側のルーティングはすべてコンテンツページとして表示されるので、ajax用のJSONを返すページ(エンドポイント)を作り、そこへPOSTかGETでアクセスさせればajax通信できるわけではありません。
ですが、WordPressの管理画面はajaxをバッキバキにキメていて、そのための機能が用意されておりますので、そちらを使ってajax通信を行います。
基本的な実装の流れはこんな感じです。
wp_ajax_ホニャララ
というアクションフックを追加し、そのアクションフックに関数を登録。
- POSTかGETでのリクエストを受け取って、求めているデータをJSON形式で返却する関数(アクションフックに登録する関数)を作成。
- データ取得用のJavaScriptの作成。
実際に作ってみよう
では、先ほどの流れを基に何かしら作ってみます。
前述の図にあった、URLからサイト情報を取得するajaxを実装してみます。
また、ここで使うプラグイン接頭辞はwpmra_
とします。
1. アクションフックの追加
ここで追加するアクションフックは、後述するエンドポイントにフックさせることでアクションフックに登録した関数を呼び出すようになっています。
そのため、アクションフックの名前はwp_ajax
と自分で決めたアクション名を繋げたものになります。
wp_ajax_ホニャララ
のホニャララ
の部分を決めて追加します。
プラグイン接頭辞を含め、以下の様なアクション名と関数名にしました。
add_action('wp_ajax_wpmra_fetch_site_info', 'wpmra_fetch_site_info');
また、フロント側で使いたい場合、WordPressへ未ログインのユーザー向けにwp_ajax_nopriv_ホニャララ
というフックが用意されているので、そちらを使用します。
ですが、こちらは未ログインユーザー向けのみのものらしく、これだけをアクションフックに追加すると今度はログインユーザーには有効にならないという謎仕様になっております。
ですので、同じ関数を呼び出すアクションフックを2つ追加します。
add_action('wp_ajax_wpmra_fetch_site_info', 'wpmra_fetch_site_info');
add_action('wp_ajax_nopriv_wpmra_fetch_site_info', 'wpmra_fetch_site_info');
2. 登録した関数の作成(JSON返却用)
1.で追加したアクションフックで呼び出している関数wpmra_fetch_site_info
を作成します。
function wpmra_fetch_site_info() {
$res = array(
'status' => 'NG',
);
if(isset($_POST['post_title'])) {
// POSTで送信されたURLからRSS情報を取得する
$rss = get_wpmra_fetch_feed($_POST['post_title']);
// サイトタイトル、URLを配列へ
if($rss) {
$res['status'] = 'OK';
$res['data'] = array(
'title' => $rss->get_title(),
'url' => $rss->get_permalink(),
);
}
}
// 配列をJSON形式で出力
header('Content-Type: application/json; charset=utf-8');
echo json_encode($res);
exit();
}
// $urlからRSSのFeedデータを取得
function get_wpmra_fetch_feed($url){
include_once ABSPATH . WPINC . "/feed.php";
$rss = fetch_feed($url);
if(!is_wp_error($rss)){
return $rss;
}
}
簡単に解説しますと、WordPressのwp-includes/feed.php
を使用してRSSのURLからFeed情報を取得し、その中からサイトタイトルとサイトURLをJSON形式で出力しています。
出力後は必ずexit()
かdie()
を使って終了させます。
アクションと関数は出来ましたが、JavaScriptでJSONデータを取得するためのURLを知らないといけません。
wp_ajax_
のエンドポイントは、サイトURL/wp-admin/admin-ajax.php
になります。
フックに追加した関数を呼び出すには、リクエスト内のactionパラメータにwp_ajax_
より後ろに記載した文字列を指定する必要があります。(今回の場合はwpmra_fetch_site_info
)
3. データ取得するJavaScriptの作成
custom.js
というファイルを作成し、読み込みます。
add_action('admin_enqueue_scripts', 'enqueue_wpmra_script');
function enqueue_wpmra_script(){
wp_enqueue_script('wpmra_js', '/path/to/custom.js', array('jquery'), '0.1');
}
このjsファイルにデータ取得する処理を書いていきますが、ここで一つ問題が。
先ほどwp_ajax_
のエンドポイントはサイトURL/wp-admin/admin-ajax.php
だと説明しましたが、サイトURLは開発環境、テスト環境、本番環境で変わっていきます。
また、この処理をプラグインに実装するとなると、余計に変わります。
JavaScriptにサイトURLの判定処理を書くのも何なので、wp_localize_script
という関数でPHPからjsに渡すようにします。
PHPファイルにscriptタグで直接書けば良いのでは?という意見もあると思いますが、横着せずPHPはphpファイルに、JavaScriptはjsファイルで管理するよう心がけましょう。
add_action('admin_enqueue_scripts', 'enqueue_wpmra_script');
function enqueue_wpmra_script(){
wp_enqueue_script('wpmra_js', '/path/to/custom.js', array('jquery'), '0.1');
wp_localize_script('wpmra_js', 'WPMRAJS', array('endpint' => admin_url('admin-ajax.php')));
}
wp_localize_script
の第2引数の文字列がcustom.js
でのグローバルオブジェクトになります。
第3引数に渡している配列でWPMRAJS
というグローバルオブジェクトに値がアサインされます。
これでJavaScriptを書ける準備が整いましたので、書いていきます。
jQuery(function(){
// URL情報を取得するボタンを押したらサイト情報を設置する
jQuery("#wpmra_fetch_site_info").on('click', function(){
// 記事タイトルに入力されたRSS Feed
var post_title = jQuery('input[name="post_title"]').val();
jQuery.ajax({
url : WPMRAJS.endpoint,
type : "POST",
// actionパラメータに、実行したいアクションの「wp_ajax_」より後ろの文字列を指定
data : {action : 'wpmra_fetch_site_info', post_title : post_title },
success : function(res){
if(res.status === 'OK') {
jQuery('input[name="mra_rss_title"]').val(res.data.title);
jQuery('input[name="mra_rss_feed_url"]').val(res.data.url);
}
if(res.status === 'NG') {
alert("取得に失敗しました。");
}
return false;
}
});
});
});