URLクエリ文字の値渡しの思考回路が完全に逆向きだったことにやっと気づく。
2018/05/02
URLクエリ文字列(URL QUERY_STRING)ってご存知ですよね。
ブラウザのアドレスバーに表示された「http://exsample.com/?p=1&m=1」みたいなやつで、
「?p=1&m=1」部分でURLの先のページに変数名と値を渡すという仕組みです。
こうした仕組みをWordPressは内部的に自動で行って、様々なデータを表示しています。
さてこれをカスタムしようと思った時、考え方が全く逆だったことに気づきましたのでご紹介。
当然、URLに直に現れていますし、ユーザーさんが勝手に書き換えることもでき、
セキュリティー云々のケースでは使えません。
ただ、これ便利なのはURLとしてSNSなどにシェアしたりすることが簡単というメリットもあります。
概要
URLクエリ文字の値渡しの思考回路が完全に逆向きだった。
「逆」って何が?と思われる事でしょう。
やりたい事
当然、やりたい事の目的によっては逆でもなんでもないと思うのですが、
今回やりたかったのは以下の様な処理でした。
- 独自で表示する4000件程度の表データをレスポンシブで表示したい。
- 4000件では遅いので500件程度に分けて、ページ分割して表示したい。
- テーブル下部には[<< 1 2 3 4 >>]のようなページ送りリンクを付けたい。
- リンクによって取得するデータを1~500や、501~1000などデータベースから取得する。
まぁ普通によくあるデータ表示の仕組みをWordPress上のショートコードで表示したい訳です。
AJAXで動的にクエリ投げて取ればいいじゃねーかってのもあるんですが、
また別のプログラムを別に作ってそこに要求投げて・・・受け取って表示。
デバッグもしにくいしできれば避けたい。
だって、何らかのアプリじゃなくて単にテーブル表示するだけなんですよ。
それも、あって8ページ程度の。
URLクエリで開始レコードを指定すればいいんじゃね?
最初に考えたのが、
URLで「http://exsample.com/?rec=1」など開始レコード位置を指定したいと。
501~なら「http://exsample.com/?rec=501」のように。
しかし、これだと誰でも「http://exsample.com/?rec=125」とか書き換えられるよねと。
別に書き換えられても構わないっちゃ構わないのだけど、気持ちは良くない。
やっぱりクエリ文字列は隠したいよね
となるとやっぱりクエリ文字列を隠したいという要求が自分の中で出てくる。
「http://exsample.com/?rec=501」と指定する場合には、
「http://exsample.com/rec/501/」とかにすればいいんじゃないか。
頭の中が「?rec=501」を隠しておきつつ、
内部的には「$url_var[“rec”] 」のように値にアクセスできたらいいなと。
仕組み的にはどうしたいのか?ってだけなので、
別に答えなんてないようなものなのですが、
PHPなりWordPressの関数仕様などを見ていると、なんか読みにくい。
読みにくい理由が、自分の脳内が逆向きのベクトルだったからなのです。
ページ内のリンクが「?rec=501」とか含んじゃ隠ぺいの意味ないだろ
そうなんですよね。
「?rec=501」というURLの要求があったら「rec/501/」へリライトして、
内部処理では「$url_var[“rec”]」のように値を取る
・・・のではなく
「rec/501/」への要求は、「…/?rec=501」へとリライトして、
内部処理では別のphpファイルのURLに疑似アクセスをさせて
「/?rec=501」というパラメータを渡す。
なのですね。
最初のURLリンクの段階で「http://exsample.com/?rec=125」って出てたら、
遷移先のアドレスバーがいくら「http://exsample.com/」になっていたとしても、
PC上などでマウスオーバーすればリンク先は見えるし、全く意味がない。と。
特定のディレクトリへのアクセスを「クエリ文字列」付きURLにリライトする
結局のところ、
特定のディレクトリへのアクセスがあった時には、
それは実質パラメータとして内部解釈して、プログラムにクエリ文字列として値を渡す。
こういうアプローチなんですよね。
この「クエリ文字列」の仕組みを起点で考えていたから、
やたらとクエリ文字列をリライトしてURLを表示したいって考えになっていた。
「http://exsample.com/?rec=501」から、
「http://exsample.com/」にURLを変更してアクセスをさせるって、
そもそも「リライト」じゃなくて「リダイレクト」ですよね。
「http://exsample.com/rec/501/」へのアクセスを、
URLそのままで内部的には「http://exsample.com/pgm/data.php?rec=501」に
リライトしてサイト側が処理をする。
こちらが普通のアプローチなんだわな。
通りでヘルプ読んでいても、なんか理解がしにくかった。
だからURLのリライト例も
大半が「ディレクトリ→URLクエリ形式」ばかりなんですね。
とほほ。
ずーっと、URLクエリ文字列で渡した値が、
URL変更後に取れない・・・って悩んでた。
そりゃURLパラメータを付加していないのに、値が取れるわけないだろと。
URLクエリ文字列による値の受け渡しは、
「ディレクトリ → URLクエリ形式」で内部的処理で隠ぺいするわけであって、
「URLクエリ形式 → ディレクトリ」にURLを変更するわけじゃない。
だからWordPressなどのページが何らかの隠しパラメータを受け取って、
そのまま処理ができるような仕組みになっていれば、
1つのURLで動的に処理をさせることが可能になる。
ってことか。
実際にはどうするのか?
functions.phpに対して、以下のようにカスタムクエリパラメータの定義を追加する。
1 2 3 4 5 |
function add_query_vars_filter( $vars ){ $vars[] = "test_parameter"; return $vars; } add_filter( 'query_vars', 'add_query_vars_filter' ); |
次に、URLのリライト設定を定義する。
functions.phpに対してリライト規則を定義する。
ただWordPress上で動いていて、
パラメータの渡し先が実体のないファイル(hogehoge.phpなど)の場合は、
WordPressが認識可能なパラメータ形式でURLリライトをした方が楽な模様。
WordPressの記事も固定ページも元々実体はなく、
TOPのindex.phpが処理しているのはご存知の事、そしてこの記事の投稿IDは「38689」です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
function test_flush_rewrite_rules() { global $wp_rewrite; $wp_rewrite->flush_rules(); } function test_custom_endpoint( $wp_rewrite ) { $feed_rules = array( '2018/05/query_string-approach-is-reversed/(.*)/?$' => 'index.php?p=38689&test_parameter='.$wp_rewrite->preg_index(1) ); $wp_rewrite->rules = $feed_rules + $wp_rewrite->rules; return $wp_rewrite->rules; } add_filter( 'generate_rewrite_rules', 'test_custom_endpoint' ); add_filter('init', 'test_flush_rewrite_rules'); |
この場合「’2018/05/query_string-approach-is-reversed/(.*)/?$’」部分で、
この記事のURI「’2018/05/query_string-approach-is-reversed/」に続いて、
「hogehoge/」または「hogehoge」とすることで、
「index.php?p=36076&test_parameter=’.$wp_rewrite->preg_index(1)」でURLをリライトする。
WordPressの起点であるindex.phpに対して、
「?p=36076&test_parameter=’.$wp_rewrite->preg_index(1)」とクエリパラメータを渡すので、
「$wp_rewrite->preg_index(1)」の部分は置換前の文字列で()で囲った部分が流し込まれる。
「/(.*)/」としているので「/」から「/」までに入力した文字が、
パラメータの値として渡される。
ちなみに、このページはWordPress的に言えば「投稿」にて公開しています。
どうも、この方式でいくと「投稿」へリライトする場合には「index.php?p=xxx」でOKなんですが、
「固定ページ」にリライトする場合には「index.php?p=xxx」ではうまくいかず、
「index.php?page_id=xxx」とする必要がありました。
上手くいかない場合には「?page_id=」で試してみて下さい。
うーん、どちらでも普通はURLとして有効なハズなんだけどなぁ。。。
https://rensrv.com/?page_id=38689
どっちでもパーマリンクとして有効なんですけどねえ。
パラメータ受け取りの確認
実際には以下のように機能するが、まず以下URLにアクセスする。
このURLはこの記事のURLの後ろに「hogehoge/」を付けただけのものです。
https://rensrv.com/2018/05/query_string-approach-is-reversed/hogehoge/
この投稿で正しく値が受け取れているのかを確認する。
「hogehoge」と表示されていれば、正しく値は受け取れている。
別に「hogehoge」以外でもブラウザでURL変えれば、その値が表示される。
なんでもいいの?
処理は以下のようにショートコードで受け取って表示している。
1 2 3 4 5 6 7 8 9 10 11 |
<?php function cc_test_wp_query_vars_handler() { global $wp_query; if( isset( $wp_query->query_vars['test_parameter'])) { $res = urldecode (htmlspecialchars($wp_query->query_vars['test_parameter'])); }else{ $res= false; } return print_r($res,true); } add_shortcode("cc_test_wp_query_vars", "cc_test_wp_query_vars_handler"); |
ご参考になれば幸いです。
ちなみにここまで来るまで、様々な検証を以下でやっていたという・・・分かれば簡単な事なのに。
地味に、こういうことやりたいなって思って、諦めてる人多いと思うんですよね。
実は自分、頭の中ではずっと考えてて、でもできなくて、色々検証しながらやっと気づいた。
WordPress上でカスタムプログラムを個別に実装したい時なんか、
こういうパラメータ渡しがもっと簡単だったら視野が広がっていいと思う。
なんか、別に記事にしろよと怒られそう(笑)
というわけで、URLはディレクトリ形式か何かで公開して、
内部的にはURLクエリパラメータで処理するって感じがスマートかと。
当然ながら、WordPress上でも「hogehoge」なんてURLは実際存在しないのであしからず。
すべてこの記事へ処理を投げて表示しているという話です。
細かな検証過程を以下に記載しました。
併せてお読みいただければ幸いです。
当サイト内のコンテンツおよび画像を含むすべてにおいて、管理人アルゴリズンが著作権を保持しております。
当サイトでご紹介しております写真等につきましては著作権の放棄はしませんが、
ライセンスフリーでご利用いただいて構いません。
コンテンツを有益であると感じていただけましたら非常に光栄です。
ありがとうございます。
サイト内コンテンツを引用される際には、出典元として当サイト(個別記事)へのリンクをお願いいたします。
申し訳ございませんが、無断転載、複製をお断りさせて頂いております。
関連記事
-
WordPressの常時SSL化前のメディアsrcのURLが「currentSrc:」で自動「https:」化される!
WordPressの常時SSL化の一番面倒な点が、記事に貼った画像が絶対パスで格 …