僕のブログには一覧ページというものがあるのですが、ここに最近素敵なフォームをつけました。なんと、一覧ページのソート順を変更できるんですね。誰かが羨ましがったら教えてあげようと思ったのですが、誰も聞いてこないので自分で書きました。
このフォームのソースはこんな感じです。
<form method="get" id="sorter" class="dark_bg center"> <p> <?php if(is_search()): ?> <label>検索<input type="text" name="s" value="<?php the_search_query(); ?>" /></label> <?php endif; ?> <select name="order"> <option value="ASC"<?php if(isset($_REQUEST['order']) && $_REQUEST['order'] == 'ASC') echo ' selected="selected"';?>>昇順</option> <option value="DESC"<?php if(!isset($_REQUEST['order']) || $_REQUEST['order'] != 'ASC') echo ' selected="selected"';?>>降順</option> </select> <select name="orderby"> <option value="date"<?php if(!isset($_REQUEST['orderby']) || $_REQUEST['orderby'] == 'date') echo ' selected="selected"';?>>公開日</option> <option value="modified"<?php if(isset($_REQUEST['orderby']) && $_REQUEST['orderby'] == 'modified') echo ' selected="selected"';?>>最終更新日</option> <option value="title"<?php if(isset($_REQUEST['orderby']) && $_REQUEST['orderby'] == 'title') echo ' selected="selected"';?>>タイトル</option> <option value="comment_count"<?php if(isset($_REQUEST['orderby']) && $_REQUEST['orderby'] == 'comment_count') echo ' selected="selected"';?>>コメント数</option> </select> <input type="submit" class="submit button" value="SORT!" /> </p> </form>
ちょっとselected属性を出すのがめんどくさいですが、ようするにGETリクエストで色々値を渡しているだけです。
なんでこんなことが可能なのか
この他にも色々できることはあるのですが、基本的に知っておけばいいのは、以下の2点です。
- WordPressはURLから求められるコンテンツを類推して表示している
- URLはごにょごにょ解析され、最終的にquery_postsに渡される
とりあえずこれを理解し、以下の例を見てみましょう。
ex.1 どの一覧ページでも検索してみる
たとえば、僕のブログにおいてカテゴリーWeb制作のURLは以下になります。
https://takahashifumiki.com/topics/web/
これの尻尾に検索クエリをつけてmootollsを含むURLにしてみます。
https://takahashifumiki.com/topics/web/?s=mootools
そうすると、mootoolsを含む投稿だけが表示されます。不思議ですね!
ex.2 日付一覧を古い順にしてみる
僕のブログの2011年10月のエントリー一覧は以下のURLです。
https://takahashifumiki.com/date/2011/10/
これを古い順にしてみます。
https://takahashifumiki.com/date/2011/10/?order=ASC
どうでしょう、 古い順になってますよね。
このように、WordPressはURLに色んなクエリ(?key1=value1&key2=value2)を渡すことで、表示される結果がコントロールできるということです。このkeyとvalueに何を使えるかは、Codexを参考にしてください。色々あります。
絞り込み検索を実装してみる
おそらく需要が高いであろう絞り込み検索もそんなにめんどくさくありません。ためしに僕のサイトで、カテゴリーが「その他(ID:10)」または「文芸活動(ID:3)」に属していて、なおかつ「web」という単語を含むページの一覧を表示するためには以下のURLでOKです。
つまり、こういう値を渡してくれるフォームを作ればいいだけですね。ただし、カンマ区切りで値を渡してくれるインターフェースはないので、Javascriptでサポートする必要があります。
<form id="search-form" method="get" action="<?php bloginfo('url');?>"> <label><input type="text" name="s" value="<?php the_search_query(); ?>" /></label> <p> <?php //登録されたカテゴリーを名前の昇順で取得 $cats = get_categories(array('orderby' => 'name', 'order' => 'asc')); foreach($cats as $cat){ //ループ処理でカテゴリーを全部出力 printf('<label><input class="cat" type="checkbox" value="%d" />%s</label>', $cat->term_id, $cat->name); } ?> </p> <input type="hidden" name="cat" value="" /> <input type="submit" value="検索" /> </form>
本当は現在設定されているカテゴリーを選択済みにする処理などあるのが望ましいですが、割愛。get_categoriesについてはCodexを確認してください。
上記で出力されたフォームだけだとcatが常に空っぽになってしまうので、こんなJavascriptを読み込みます。
jQuery(document).ready(function($){ //フォーム送信直前に実行 $('#search-form').submit(function(e){ //チェックボックスのチェック済みをすべて取得 var cats = []; $('input.cat:checked').each(function(index, elt){ cats.push($(elt).val()); }); //1つ以上チェックされていたら隠しinputに格納 //なかったら削除 if(cats.length > 0){ $('input[name=cat]').val(cats.join(',')); }else{ $('input[name=cat']).remove(); } }); });
これでカテゴリーによる絞り込み検索は実装できます。他にもタグとかカスタムフィールドとかもできるので、色々試してみてください。ポイントはCodexをよく読むことです。
さらなるカスタマイズは茨の道
よくWordPressを導入した場合に言われるのが「Googleみたいに便利な検索機能をつけられないか」ということなのですが、これが難しいのは技術的な問題もさることながら、もっと高次な問題があるように思います。「ゆらぎ検索」や「低レイテンシ」などの様々な技術的難題を突破したとしても、最後に「どんな基準で表示するか」という最大の難問が発生するからです。逆に言えば、これさえわかってしまえば答えは出たも同然です。
Googleが便利なのは「どんな順番で検索結果を表示するとユーザーが便利だと思うか」ということだけを考えているからです。基準もちゃんと持ってます。
- たくさんのサイトからリンクされているWebページはいいページ
- いいサイトからリンクされているWebページはいいページ
- 東京の人は東京の店舗情報を知りたいに違いない
- 友達が進めているWebページは気に入るに違いない
最近はどんどんパーソナライズの方向へ向かっているので、Googleならびに各種検索エンジン・SNSはこうしたデータをやっきになって集めているのですね。便利さはあくまで結果でしかないわけです。
翻ってWordPressのことを考えてみると、よくも悪くもブログシステムが元になっているので、発想の根本がブログ(つまり日記)です。このエントリーで紹介しているソート機能というのは、突き詰めれば「コンテンツをどう評価するかの基準」ということになります。WordPressは日記が元なので、時系列がデフォルトのソート順になっています。
WordPressはデフォルトのままだと「いまこのサイトを誰が見ているか」も知らないし、「このページがどれだけアクセスされたか」もわかりません。評価しようにも評価するべき基準がないのです。この基準を集めるのは結構大変です。ちょっと幾つか具体例を考えてみました。
ケーススタディ1 PVでソート
PVというWordPressが持っていない外部的な指標によってコンテンツをソートする場合を考えてみます。これはMySQL知らなくてもできますね。僕もまだ実践したわけではなく、今度こういうのを作ろうと思っているだけなので、概要だけサラッと。
- Google AnalyticsでAPIを叩いて特定のURLを取得する
- 取得したPVをカスタムフィールドに保存する
- 上記の処理をwp_cronなどで毎週実行する
こんな感じでPVという情報を投稿に不可することは可能です。とりあえずこれでWordPressに「どれだけの人は見たか」ということを教え込ませることはできたので、色々ソートできます。まあ、この程度のことしかやらないなら、Jetpackに入ってるstats使った方が楽ですね。
ケーススタディ2 はてなブックマーク方式
ここからMySQLの知識が必要になります。WordPressはデフォルトだと、タグと投稿は1対1の関係になります。これをテーブル構造的に見るとこうなります。
これだと、タグはあくまで投稿のメタデータにしかならず、あんまり有用な情報ではありません。日付とかと一緒ですね。
一方、はてなブックマークはタグとURLは紐づいていますが、さらにそのタグとURLに対する関係にユーザーが入ってきます。「誰がどのURLにどんなタグをつけたか」ということですね。これをテーブル構造的に見るとこうなります。
これはWordPressのテーブル構造にないので、作らないといけなくなります。これは単にデータベースをphpMyAdminで作ればいいというだけのことではなく、CRUDというデータの保存・検索・更新・削除の機能をつけなくてはいけないですし、一覧ページをどうやって出力するかも考えなくてはなりません。ここら辺になるとフレームワークを使った方が早いんじゃないかなーと思い始める人が出てきますね。
ただ、コンテンツを漫然と並べ立てるだけでは飽き足らなくなった場合、これは避けて通れない道だと思います。Web制作業についているだけであれば、学習コストや開発工数をトレードオフして「やらない」という結論もぜんぜんアリだとは思うのですが、コストを度外視してでも実現したいものがある人は、ぜひMySQLを勉強してみることをオススメします。そうじゃないと、新しいものを作れないような気がします。その理由は次節。
凡庸・オア・ダイ
最近破滅派をリニューアル作業をしていてとみに思うのが、データをどのように蓄積してどのように評価するかが結局キモでありコンテンツなんだなーということです。ちょっと前ですが、はてなからGREEに移籍した伊藤直也さんが古巣に提言した内容もそうなんですが、最近ちょっとエッジの効いたサービスをやろうと思ったら、ユーザー最適化などは避けて通れないですね。ロラン・バルトが言ってた作者の死ってこういうことだったんですかね。
PVや「いいね!」「はてぶ」の数などの外部的な指標を上述したような単純なやり方で自分のサイトに持ち込んでも、結局は同じ結果になると思います。伊藤直也さんは「衆愚」という言葉を使っていましたが、たしかにSFの90%はクズだが、そもそもあらゆるものの90%はクズである
とか、どこに国に行っても馬鹿の数が一番多い
とか、民主主義は最悪の政治制度だ、ただしこれまで試みられたあらゆる政治制度を除けば
と言い換えてもいいかもしれません。はてなブックマークのトップを見ていると、「いつまで部屋片付けてんだ?」「何年TOEIC勉強してんだ?」って思うことしきりですからね。こんなこと書くと炎上しますかね。
ともかく、集計&ソーティングというのはすでに陳腐な技術であり、そこらへんのフリーソフトでサクッと実現できてしまいます。その結果、どんな指標を使ったにせよ、出来上がるものは大体似たようなものになってしまいまそうな予感。このままいったら僕らはみんなマトリックスにつながれて、偽物の幸福な夢を見ながらGoogleの餌になるしかないですよ。
ちょっと話が大きくなりましたが、ますます便利になりつつあるインターネッツの世界でエッジの効いたデータ提示をしたかったら、茨の道だけどMySQLいじるようにした方がいろいろ捗るぞというメッセージでした。
マトリックス スペシャル・エディション【字幕版】 [VHS]
価格¥33
順位259,396位
出演キアヌ・リーブス
監督アンディ・ウォシャウスキー, ラリー・ウォシャウスキー
Unknownキアヌ・リーブス
発行ワーナー・ブラザース・ホームエンターテイメント
発売日2000 年 3 月 24 日