大量のFORM送信をコンパクトにする方法。
プラグイン「WP Theme ShapeShifter Extensions」のポストメタによるオプショナルアウトプット機能が、5つ程度しかアイテムを保存できなかった問題があり、「ブログ・更新情報」でもデータを1つにまとめれば何とかなるかもと思って書いたのですが、実際に試してみました。
問題のあったオプショナルアウトプット機能での例を用いて紹介していきますので、更新したプラグイン「WP Theme ShapeShifter Extensions」最新版を参考にしていただければと思います。
JavaScriptが使える環境であれば(使えない環境の方が珍しいと思いますが)、ワードプレス以外でも使えると思いますので、僕みたいな状況に陥っていた場合は試してみてください。
オプショナルアウトプットの問題点
プラグイン「WP Theme ShapeShifter Extensions」には、ポストメタ(ページ毎の設定)によりウィジェットエリアにアイテムを出力できる機能がテーマ「ShapeShifter」に追加されます。
ええ、ウィジェットをコンテンツページの編集で追加できますので、ウィジェットだけで良いのであれば、それだけでコンテンツを作成できてしまうような機能なのですが、選択肢を多く用意していて、その値によって表示・非表示のみを行って、編集できるようにしていたのですが、保存するために送信するデータが膨れ上がってしまい、アイテムが多くても5つ程度しか保存できないようになってしまっていました。
保存処理が上手く行かないのではなく、送信自体出来ていませんでしたので、メタボックスのFORMタグで送信できるデータの数が決まっていることを初めて知って焦ったという訳です。データのサイズではなく、例えば、大量のINPUTによって、数多くのデータを送信する場合の話です。
で、これじゃいかんということで、膨大になったデータを1つのINPUTタグの値にまとめてしまうことにしました。
JSONを1つのINPUTタグに
用意したINPUTタグなどのデータを1つの変数にまとめてしまって、INPUTタグに入れてしまうこと自体はテキスト(String)形式にすれば大丈夫なのですが、INPUTタグのNAME値には[]で囲って配列化されたものを受け取れるようになっています。
ええ、僕は関数を知らなかったので、テキスト形式からPHPで受け取りたかった連想配列形式に変換することと、それと同時にサニタイズして、出力時に使用する値に反映させる作業が非常に面倒でした。
まずは「JSON.stringify( jsonData )」まで
INPUTタグなどが使用されているラッパー要素をjQueryで指定して、「input」「textarea」「select」など取得したいデータを持つ要素に「addClass」でクラスを与えてマーキングしていきます。
$( wrapperSelector ).find( 'input, textarea, select' ).addClass( markClass );
次にマーキングしたクラスを指定して、JSON形式の変数に、jQueryなどで「name」属性値をキーにして「value」値を取得させていきます。
この時、僕はJavaScriptに慣れていなかったのでPHPで受け取ってから処理しましたが、先に「[child]」内の値をキーにして、階層を持たせるようにしておくと後が非常に楽になると思います。
var jsonData = {}; $( markClass ).each( function( index ) { name = $( this ).attr( 'name' ); jsonData[ name ] = $( this ).val(); // Should be get the conditional Value ( For Example, checkbox ) });
あとは、「送信ボタンのクリック時」にトリガーさせて、「JSON.stringify( jsonData )」を送信用の「hidden」タイプのINPUTタグに与え、マーキングしたクラスを全て「disabled」にしてしまうだけです。
$( submitSelector ).on( 'click', function() { // 上の処理を実行 // JSONをテキストにしてINPUTタグへ $( 'input#json-data-collection-of-settings[type="hidden"]' ).val( JSON.stringify( jsonData ) ); // マークした要素に「disabled」属性を与えて、Form送信しないように。 $( markClass ).prop( 'disabled', true ); });
まぁざっくり書きましたが、これで「hidden」タイプのINPUTタグからのみJSONのStringデータを受け取ることが出来るようになり、マークしたINPUTタグからは何も送信されなくなります。
[child]が残らないように配列化処理
JSONのテキスト形式の値を受け取るとエスケープもされているので、ちょっと不便な形になっています。直接「json_decode」が使えない状態になっているんですよ。
僕は手っ取り早くするためにMySQLに一旦保存してアンエスケープ(?)して、その保存した値を取得することでそのまま「json_decode」できるようにしています。テキストも元々保存するつもりでしたから、個人的には有りだと思っています。
あとは「json_decode」で連想配列化してから、「[child]」毎に階層を作って整理してやればOKです。
僕はPHPで処理したのですが、JavaScriptで処理したのであれば不要の処理です。というか僕もJavaScriptで処理できるようにしようと思っています。
恐らくこれが本来の方法
じゃないか、とようやく思い至った訳です。
もともとFORM送信できる数に限度があるとは思っていなかったので気に留めたことはなかったのですが、実際に問題に直面してみると、受信側の処理を自分で書けるなら、何かしらの方法で1つにまとめてしまった方が良いです。
お陰さまでオプショナルアウトプット機能で設定できるアイテムの数の厳しい制限が緩和されました。
余談
実は気付いたきっかけはウィジェットエリアの表示例としてこの機能を使おうと思ったんですが、数多く用意したウィジェットエリアの全てにアイテムを出力できないという事実に直面したのがきっかけです。
ええ、本来は解説用のページで僕が使いたかっただけなんです。お騒がせしました。
そりゃ特定のページにウィジェットを10個以上も追加することもないと思っていましたし、そんな人いないと思っていましたから、まさか自分がそれに該当するとは思ってもいなかったんですよ。
まぁまた何か不具合があれば修正致します。
1件のピン
[…] ータの数を調節するのにフィルターフックの存在を知りませんでしたので、結局JSONと連想配列で何とかしたのですが、ウィジェットエリアの解説ページに漸くウィジェットを出力できる […]