JavaScriptでウィジェットエリアHTMLを取得するには

ワードプレスをヘッドレスで使用することを想定すると、フロントエンド側で困るのはウィジェットな気がします。

ポストメタなどは登録の際にRESTを有効化させることもできますし、プラグインACFと合わせてRESTで取得できるプラグインもインストールできますので、この辺りは問題無いと思いますから。

そこで、標準的なウィジェットに加えプラグインにより追加されるウィジェットを管理画面で設定した通りに出力条件に適合させてHTMLを取得したい場合、それをどうしようかと考えてみました。

そこまである程度やってしまえば、あとはスタイル付けたり、ブロックなどのコンテンツ拡充に集中できるかもです。

一応僕としてはReactコンポーネントなどをフロントエンドに想定していますが、そこは自由でいいと思います。

そういったテーマも作ってみようとは思っているんですけどね。。。orz

  • Table of Contents

ウィジェットデータを取得するだけじゃダメなの?

JSONなどの形でウィジェットの設定値のみを取得する方法も勿論あります。

例えばデータのみを取得する場合、グローバル変数に「ウィジェットエリアのIDリスト」「配置されたウィジェットのID」「使用可能な登録されているウィジェット」といったデータはワードプレスが自動的に生成してくれます。

そして、これらを元にしてオプションとして保存されている各ウィジェットの設定値も取得できますので、あとは関数「the_widget()」などを使用してHTMLを生成してしまえば良いだけなんです。

問題となるのは、そのデータに条件分岐に使用されるデータが含まれている場合、あるいはそういった処理をプラグインなどで設定している場合です。

メジャーなプラグインだとJetpackで、条件を設けてウィジェットの有効性を設定するような機能があります。

各プラグインがそういった機能を有していて、用意したデータモデルに合わせて条件分岐させるなどの処理をしている場合、これをフロントエンドに押し付けるのは限度があると思いました。

せいぜい1つか2つのプラグインまでは対応しても良いかもしれませんが、使用する全部のプラグインの条件まで見てられなくなります。

ユーザーがプラグインを増減する度にその多様性が左右されてしまいますから。

ですから、JavaScriptでウィジェットを扱う場合に関しては、データを取得するよりもその設定値が反映されたHTMLを丸ごと取得する方が都合が良いと思うんです。

まぁ他に良い方法があるのかもしれませんので、一応個人の見解と。

出力時にHTMLを保存してテンプレート化する方法

まずはウィジェットエリアHTMLを丸ごと保存してしまう方法が簡単でしょう。

$widget_areas = [];

...

ob_start();
dynamic_sidebar( $id );
$widget_areas[ $id ] = ob_get_clean();

あとはJSON化させて貼り付けてしまえば、JavaScriptで使用しやすくなります。

上のコードで使用している「$widget_areas」は、変数名にプレフィックスをつけてグローバル変数にしておくと良いかもしれません。

同じページ上でDOM操作することを前提にするならば、scritpタグでテンプレートとして出力してしまって良いんじゃないでしょうか。

// scriptタグでテンプレート化させる場合
<script id="<?php esc_attr( $template_id ); ?>" type="template/text">
<?php dynamic_sidebar( $id ); ?>
</script>

こんな感じで取得したHTMLを格納したり、あるいはscriptタグで囲ってテンプレート化させてしまう方法もあると思います。

結構簡単な方法だと思いますが、配列にHTMLを保存してしまって、REST APIなどで他のページのデータとして取得しやすいように加工してやっただけです。

ちょっとごちゃごちゃした形になりますが、レンダリングされた状態には見えない部分ですし、目を瞑ることはできるのかもしれません。

AJAXで拾ってくる方法

こっちはちょっと面倒な方法かもしれませんが、ワードプレスにAJAX用のフックが用意されていますのでこれを利用します。

ただ、心配になるのが、ウィジェットエリアを丸ごと取得する際、テーマやプラグインなどによりウィジェットの出力条件などが反映されるかどうかという心配があるでしょう。

僕も最初これを考慮してAJAXで取得することを躊躇っていたのですが問題なく取得できますので、その手順について簡単に解説します。

コールバックにクエリを設定

ウィジェットエリアの取得には前の項目で紹介したように「dynamic_sidebar」を使用するだけで簡単なのですが、ワードプレスでAJAXリクエストのレスポンスを設定をする場合、最初に仮装的な環境をセットアップすることで、ウィジェットエリアあるいは各ウィジェットの出力条件を反映させることができます。

まず、AJAXのセットアップは通常の方法です。

「wp_ajax_{$action}」と「wp_ajax_priv_{$action}」にフックさせて、コールバックを用意です。

この関数内でリクエスト元から、そのページにおけるクエリを取得することで解決します。

標準的なワードプレスのページからクエリを送信する例ですと、アクションフック「wp」以降においてメインクエリがセットされていますので、これよりクエリを抽出してローカライズさせた形をリクエストしてやります。

実際にはこんな形になります。

global $wp_query;
$query = $wp_query->query;
// 受け取りやすい形に処理
wp_localize_script( $handle, 'yourQueryObj', $query );

これにより、現在ページのクエリをJavaScript側で「yourQueryObj」として取得できます。

別のフロントエンドフレームワークからこのクエリを生成するのがちょっと難題というか面倒かもしれませんが、ワードプレスで使用可能なクエリを渡してやることを覚えておけば良いと思います。

ただ、ワードプレスをヘッドレスなCMSとして使用する場合でも、恐らくページのルーティングをワードプレスに合わせるでしょうから、クエリも同様に生成できるはず。

あとはこれをAJAXのリクエストの際に送信して、AJAXのコールバック内でリファラチェックなどをした後、受け取ってパースしたクエリ(下のコードでは「$query」)を使用し、メインクエリを「query_posts」でセットアップします。

query_posts( $query );

これで仮装的に(?)AJAXリクエストのコールバック内が、リクエスト元のページと同様のメインクエリにセットアップされます。

例えば、「is_single()」などがクエリの条件にあった結果を返すようになります。

あとは「dynamic_sidebar」でウィジェットエリアを出力・取得することで、出力条件を反映させたウィジェットエリアHTMLをJavaScriptで取得できますよ〜。

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください