【WordPress】Ajaxを使って投稿記事を表示する

この記事はブログとプログラミングで生計をたてている海外在住ウェブディベロッパーがわかりやすさにこだわって作成しました

はじめに

そもそもAjax*とはなんでしょうか。ごくごく簡単にいうと、JavaScriptを使って非同期通信を行うことです。

wpはajaxの機能があらかじめ備わっています。この機能を使えば、投稿画面でAjaxを利用してブラウザで画面を更新することなく投稿データをアクセスすることがができます。

今回は、テンプレートに対象の投稿データをAjax通信によりデータを取得してダイアログボックスに表示する機能を作成してみました。

Ajax*)Ajaxは「Asynchronous JavaScript + XML」の略称です。

WPに最新jQueryを読み込む

WordPressはAjax通信に必要なjQueryは備わっています。しかし、jQueryのバージョンは最新ではありませんので、最新バージョンのjQueryを読み込むようにします。

WPにスクリプトまたはスタイルシートの読み込むは、次のAPIを使用します。

  • wp_enqueue_script スクリプトの読み込み
  • wp_enqueue_style スタイルシートの読み込み

スクリプトまたはスタイルシート読み込みAPIの実行は、wp_enqueue_scriptsフックをを使用します。(フッター読み込み時に処理を行いたい場合は、wp_footerフックに変えてください)

add_action( 'wp_enqueue_scripts',{スクリプトまたはスタイルシートを読み込む関数名});

 

wp_enqueue_script

<?php wp_enqueue_script( $handle, $src, $deps, $ver, $in_footer ); ?>

この関数を呼び出す際に使うべきアクションフックについての情報はセクションをご覧ください。

パラメータ

$handle
文字列) (必須) スクリプトのハンドルとして使われる名前。特別なケースとして、文字列に '?' という記号が含まれている場合、それより前の部分は登録されたハンドルとして参照され、それより後の部分はクエリストリングとして URL に追加される。このような特別な場合、バージョンを使用する必要がある。

初期値: なし
$src
文字列) (オプション) スクリプトの URL。例: http://example.com/wp-content/themes/my-theme/my-theme-script.js。ローカルスクリプトの URL は絶対に直接書き込むべきではない。代わりに plugins_url (プラグイン向け) と get_template_directory_uri (テーマ向け) を使って適切な URL を取得する。リモートのアセットはプロトコルに影響されない URL で指定できる。例: //otherdomain.com/js/their-script.js。「WordPress に含まれ登録されているデフォルトスクリプト」を参照。

初期値: false
$deps
配列) (オプション) このスクリプトが依存するスクリプトのハンドルの配列、つまり、このスクリプトより前に読み込まれる必要があるスクリプト。このパラメータは、$handle のスクリプトが wp_register_script() を使って登録されていない場合のみに必要。デフォルトのハンドルはすべて小文字。

初期値: array()
$ver
文字列) (オプション) クエリストリングとしてファイルパスの最後に連結される、スクリプトのバージョン番号を指定する文字列 (存在する場合) 。バージョンが指定されていない場合は false に設定され、WordPress は自動的に現在の WordPress のバージョン数と同じバージョン番号を追加する。null に設定した場合はバージョン番号は追加されない。このパラメータはキャッシングに関わらず正しいバージョンがクライアントに送信されるようにするために使う。したがって、バージョン番号があってそれがスクリプトに意味を持つ場合は含めるべきである。

初期値: false
$in_footer
真偽値) (オプション) スクリプトは通常 HTML ドキュメントの <head> に置かれるが、もしこのパラメータが true の場合 </body> 終了タグの前に配置される。テーマ内の適切な位置に wp_footer() テンプレートタグが含まれていることが必須となる。

初期値: false

戻り値

(void)
この関数には戻り値はありません。

 

wp_enqueue_style

<?php wp_enqueue_style( $handle, $src, $deps, $ver, $media ); ?>

パラメータ

$handle
文字列) (必須) スタイルシートのハンドルとして使われる名称。特別なケースとして、文字列に '?' という記号が含まれている場合、それより前の部分は登録されたハンドルとして参照され、それより後の部分はクエリストリングとして URL に追加される。

初期値: なし
$src
文字列|真偽値) (オプション) スタイルシートの URL。例: http://example.com/css/mystyle.css。このパラメータは WordPress がこのスタイルを認識していない場合のみに必要。ローカルのスタイルには URL を直接書き込むべきではない。代わりに plugins_url (プラグイン向け) と get_template_directory_uri (テーマ向け) を使って適切な URL を取得する。リモートのアセットはプロトコルに影響されない URL で指定できる。例: //otherdomain.com/css/theirstyle.css

初期値: 空文字列
$deps
array) (オプション) このスタイルシートが依存する他のスタイルシートのハンドル配列、つまり、このスタイルシートより前に読み込まれる必要があるスタイルシート。依存関係がない場合は空の配列を指定。

初期値: array()
$ver
文字列|真偽値) (オプション) スタイルシートのバージョン番号を指定する文字列 (存在する場合) 。このパラメータはキャッシングに関わらず正しいバージョンがクライアントに送信されるようにするために使う。したがって、バージョン番号があってそれがスタイルシートに意味を持つ場合は含めるべきである。

初期値: false
$media
文字列|真偽値) (オプション) スタイルシートが定義されているメディアを指定する文字列。例: 'all'、'screen'、'handheld'、'print'。有効な CSS-media-types の全容についてはこちらの一覧を参照。

初期値: 'all'

戻り値

(void)
この関数は値を返しません。

jsのグローバル変数を定義する

フロントエンド側でAJAXを使用するとき、WORDPRESSならではの規則があります。あらかじめ必要な情報はfunctions.phpで定義して、ビュー側(テンプレート)で使用できるようにしておいたほうが便利です。

そのためには、phpの配列変数をJSで参照できるオブジェクト型に変換するAPI(wp_localize_script)を使用します。

※wp_localize_scriptで生成したデータをwp_enqueue_scriptでキューに出力するだけでは、ビュー側で参照できず悩みました。実際にファイルを指定して読み込むAPI(wp_register_scriptやwp_enqueue_script)のハンドル名と同じハンドル名を使用して、wp_localize_scriptを使用することで、ファイル読み込み時に同時にJS用に変換されたオブジェクトも読み込まれます。

wp_localize_script

<?php wp_localize_script( $handle, $name, $data ); ?>

パラメータ

$handle
string) (必須) The registered script handle you are attaching the data for.

初期値: なし
$name
string) (必須) The name of the variable which will contain the data. Note that this should be unique to both the script and to the plugin or theme. Thus, the value here should be properly prefixed with the slug or another unique value, to prevent conflicts. However, as this is a JavaScript object name, it cannot contain dashes. Use underscores or camelCasing.

初期値: なし
$data
array) (必須) The data itself. The data can be either a single- or multi- (as of 3.3) dimensional array. Like json_encode(), the data will be a JavaScript object if the array is an associate array (a map), otherwise the array will be a JavaScript array.

初期値: なし

用例

<?php

// Register the script first.
wp_register_script( 'some_handle', 'path/to/myscript.js' );

// Now we can localize the script with our data.
$translation_array = array( 'some_string' => __( 'Some string to translate' ), 'a_value' => '10' );
wp_localize_script( 'some_handle', 'object_name', $translation_array );

// The script can be enqueued now or later.
wp_enqueue_script( 'some_handle' );

You can access the variables in JavaScript as follows:

<script>
    alert( object_name.some_string) ; // alerts 'Some string to translate'
</script> 

 

 

 

フロントエンド側JS

 

今回はテンプレートファイルにJSを直接書いていきます。

functions.phpで読み込み設定したjQueryが使用できるように、必ずwp_headまたはwp_footer以降にJSを記述するようにします。

 

画面に表示されているボタンをクリックすると、jQueryでクリックイベントが発生して、AJAX通信処理が起動するようにします。

画面に表示するボタンは、nameをすべて"show-item"にして、データセレクタ(id)に投稿idを設定することで、イベント発生後に、対象の投稿データの取得が可能になります。

※投稿記事を一覧表示できるプラグインListCategoryPostsのテンプレートに少し手を加えてボタンを追加しました。

 

jQueryクリックイベントの取得と、AJAXの起動はjQueryで。

$("input:button[name=show-item]").click(function() {
  $selected_id = $(this).data("id");
 AJAX通信関数の呼び出し(引数:$selected_id);
});

AJAX通信もjQueryで行えるので簡単です。

AJAX通信関数:
$.ajax({
  type: 'GET',
  url: MY_AJAX.api,
  data: {
    //functions.phpで定義済み
    'action' : MY_AJAX.action,
    // アクションに対応するnonce
    nonce: MY_AJAX.nonce,
    'id': $selected_id,
  },
  //ajax通信エラー
  error : function(XMLHttpRequest, textStatus, errorThrown) {
    //   // エラー時のデバッグ用
    resultMsg("NG", "AJAX通信エラー");
  },
  success: function( callback ){
    if(callback.status=="OK") {
    AJAXで取得した投稿データをダイアログボックスで表示する関数の呼び出し(引数:AJAX取得データ)
    }else{
      resultMsg(callback.status, callback.message);
    }
  }
});

バックエンド側PHP

 

バックエンド側では、JSからAJAX通信データが要求されたときに実行する関数をWPに登録する必要があります。

WPでAJAX通信をする場合は、決められた手続きに従って行う必要があります。

実際には、AJAX専用のフックをap_ajax_{アクション名}およびap_ajax_noprov_{アクション名}という命名方法で生成して、対象のアクション名に対応するコールバック関数を登録します。

add_action('wp_ajax_{アクション名}',{API関数名});
add_action('wp_ajax_nopriv_{アクション名}',{API関数名});

 

登録するコールバック関数はこちらです。

コールバック関数では、まずセキュリティのためnonceチェックを行います。

nonceチェックがOKなら、次にフロントエンド側で設定したパラメータを取得して、投稿データをフロントエンド側に返します。

function my_ajax_event() {
  // wp_create_nonce の引数に渡したものと同じ アクション名
  $action = 'my-ajax-action';

  // nonceのチェック
  // https://chaika.hatenablog.com/entry/2017/09/08/090000
  if( check_ajax_referer($action, 'nonce', false) ) {


    // Ajax(post)のdataから渡される値を使用する場合は $_POST から取得する (適時エスケープ)
    $id = intval( $_GET['id'] );
    //$name = esc_html( $_POST['name'] );

    // 投稿IDが10の投稿情報を取得
    $post_data = get_post($id);

    // 投稿IDが10の投稿タイトルを取得
    $title = $post_data->post_title;
    $content = $post_data->post_content;


    // 配列をjson形式にエンコード
    //$data = "<p>post_id=$id title=$title price=".print_r($price,true)."</p>";//</p>json_encode($data);
    $data = array(
      'id' => $id,
      'title' => $title,
      'content' => $content,
    );

  } else {
    // Ajaxに返す
    //status_header( '403' );
    header( 'Content-Type: application/json; charset=UTF-8' );
    echo json_encode(array('data'=> '', 'status' => 'NG', 'message' => "nonceチェックエラー", 'result' => ""));
    die();

  }

  // Ajaxに返す
  header( 'Content-Type: application/json; charset=UTF-8' );
  echo json_encode(array('data'=> $data, 'status' => 'OK', 'message' => "受信完了", 'result' => ""));

  die();
}

参考書籍

この本を1冊読めば、WordPress のアーキテクチャや開発手法がサクッと理解できる!というコンセプトで書かれた解説書です。

WordPressをカスタマイズしたい人にはおススメの良本です。WordPressは一歩踏み込んでカスタマイズするためには独特のアーキテクチャを理解する必要があります。私は独学でWordPressのカスタマイズを学びましたがほぼこの本のおかげです!

参考

 
 

■AJAXを使用する

★Ajaxを使ってWordPressからコンテンツを取得したい。

★ordPressでAjaxを使う方法の解説

jQuery UI のファイル読込みを CDN のライブラリから参照する方法

★html5のdata属性をjQueryで取得する方法

【HTML5】カスタムデータ属性(data-*)の値に複数設定、それを取得する方法

 

★WordPressテーマ開発:jQueryの正しい読み込み方法

AJAX-UI ダイアログ

WordPressでpathやURLを取得するためのタグと出力例まとめ

WINDOWSサイズ

★テーマにJavaScript(jsファイル)を正しい方法で読み込む

★jsもcssもenqueue(エンキュー)しよう!

★重要★
★WordPress標準のjQueryを使う場合の書き方

PHP/Javascript/WORDPRESS案件全般承ります

オーストラリアで主に日系企業や個人のお客様からのご依頼でお仕事をしております。この記事についてのご質問またはお困りのことがございましたら、お気軽にお問い合わせください。

タイトルとURLをコピーしました