ホーム > タグ > programming

programming

WordPressでエントリを50音順にソートする試み

WordPressのエントリを「あいうえお」順にソートしたかったのです.一般的に考えて,こんな方法で取り出します.

query_posts('showposts=-1&orderby=title&order=asc');

あると思います.しかし,これには日本語特有の問題があります.アルファベットやひらがなやカタカナはまぁまぁそこそこ思い通りに出力されると思いますが,漢字が入ると途端にダメです.当たり前ですね.「海」を「うみ」と読むのか「かい」と読むのかは字面からでは判断できません.そのため,日本語で書かれたエントリタイトルを単純な方法でソートしても,期待通りの結果を得ることはできません.

では,どうしますか?以下のような解決方法が考えられます.

  1. タイトルに漢字を使わない
  2. タイトル以外の要素を利用してソートする

タイトルに漢字を使わないというのは,なかなか強行的で,利便性への配慮が欠けすぎています.非現実的なソリューションです.非実在解決法.では,タイトル以外の要素を利用してソートすることを考えたとき,どのような手法があり得るのでしょうか.

  1. スラッグ
  2. カテゴリ
  3. タグ
  4. カスタムフィールド

まずスラッグです.スラッグは以下のように説明されています.

スラッグとは、投稿や固定ページを表すいくつかの単語のこと。スラッグは(WordPress によって自動生成された)URL に適する形式の投稿タイトルであることが多いが、その他の好きなフレーズでもかまわない。URL にあるコンテンツを説明する支援として、スラッグはパーマリンクで使われる。

用語集 – WordPress Codex 日本語版

好きなフレーズでも構わないので,ひらがなかカタカナでエントリの読みを振っておけば,ソートに利用できそうです.なかなかいいですね.

ではカテゴリはどうでしょうか.カテゴリでは問題は解決しません.エントリの数だけカテゴリを作るというなら,読みをカテゴリ名に与えて解決することもできますが,本来の利用方法から逸脱しすぎです.しかしながら,これはこれで別に役に立つ使い方があります.これは後述します.

タグを使う場合はどうでしょうか.タグに読みを与えれば解決できます.しかし,カテゴリと同じく,エントリの数だけタグが生成され,実に美しくないです.本来の用途でタグを使おうとしたときに,邪魔であるという問題もあります.ですので,積極的に採用したい解決策ではありません.

最後に,カスタムフィールドはどうでしょう.カスタムフィールドの使い方として,以下のような例示があります.

WordPress には、投稿者が投稿に「カスタムフィールド」を追加できる機能があります。この任意の情報は「メタデータ」と呼ばれており、たとえば以下のような情報を含めることができます。

  • 現在のムード: 幸せいっぱい
  • 今読んでいる本: 星の王子様
  • BGM: Rock Around the Clock
  • 今日の天気: 晴れ

さらに、ちょっとしたコードを付け加えるだけで、このメタデータに投稿の表示期限を付け加えたりすることも可能です。

カスタムフィールドの使い方 – WordPress Codex 日本語版

これは今回の目的にぴったりです.ではカスタムフィールドを使って実装しましょう.

カスタムフィールドを用いたエントリ50音ソート

まず前提として,以下を想定します.

  • カスタムフィールド名”yomi”に値として「ふりがな」を入力する
  • カスタムフィールド”yomi”を利用してエントリを50音ソートする
  • エントリタイトルは通常通りに英数漢字かなカナ混合
  • Exec-PHPなどが導入されていて,エントリやページにPHPを書ける状態である

では,以上のような想定環境下で全エントリを50音ソートさせてみます.以下のようなコードを「エントリ一覧」などとしたページに書くと,なんとなくそれっぽい出力が得られると思います.

query_posts('showposts=-1&orderby=meta_value&meta_key=yomi&order=asc');
while (have_posts()) : the_post();
echo '<p><a href="';
the_permalink();
echo '">';
the_title();
echo '</a></p>';
endwhile;

簡単ですね.

カスタムフィールドの入力を必須項目にしたい

ここからはおまけです.カスタムフィールドを使ってソートを実現しましたが,カスタムフィールド”yomi”に値が入力されていなければ,正しくソートされません.となれば,この項目は入力必須に指定したくなります.それを可能にするプラグインがCustom Field GUI Utility 3です.conf.iniを以下のように設定すれば,カスタムフィールド”yomi”は入力必須項目になります.

[yomi]
fieldname = ひらがなでの読み
type = textfield
class = post
default = あいうえお
size = 35
must = 1

もっといえば,ちゃんと「ふりがな」が入力されているかのバリデーションもやりたいところですね.そのときは,functions.phpでedit_postにフックを引っかけて,バリデーションしたら良いと思います.やってないので,コードは紹介できませんが.

201109181121追記

後述しますって書いておいて,カテゴリの使用方法を後述してませんでしたので,追記します.

50音順ソートはカスタムフィールドでやるとして,「あ行」とか「か行」とか,もっと細かく「あ」とか「い」とかやるには,カテゴリを打つのが便利です.カテゴリ毎のエントリをカスタムフィールドで並べれば良いだけなので.カスタムフィールド単体でやると,出力時に「あ」なのか「い」なのかを判別する処理を加える必要があります.それでも良いと思うけど.

参考

XML-RPCを使ってWordPressに記事を投稿する

何番煎じだかわかりませんが,備忘録として.XML-RPCを使って,スクリプトからWordpressに記事を投稿しまくる方法です.参考にしたのは以下のエントリ.

見ればわかりますが,プログラミング言語はPHPです.まずは,何はなくとも,PHPでXML-RPCを扱えないといけないので,PEARからインストールします.

# pear install XML_RPC

続いて,これもサンプルコードそのままなので,深く考えずに,書いていきます.ところが,どっこい!このエントリではカスタムフィールドの扱い方が説明されていません.なんてこったい!これは困りました.今回はカスタムフィールドに値を入れられないと,ものごっつ面倒くさいことになるような件数を突っ込むのです.ですので,どうしてもXML-RPCでやりたいので,調べたところ,以下のエントリがヒットしました.

完璧です.以上より,作成したコードは以下の通り.

require_once("XML/RPC.php");

$host = 'example.com';
$xmlrpc_path = '/wordpress/xmlrpc.php';
$appkey = '';
$user = 'username';
$passwd = 'password';

$title = 'エントリのタイトル';
$categories = array(
  new XML_RPC_Value('未分類', 'string'), );
$description = 'ここに本文を入れます.';
$custom_fields = array();
$custom_fields[] = new XML_RPC_Value(
  array(
    'key' => new XML_RPC_Value('yomi', 'string'),
    'value' => new XML_RPC_Value('ふりがな', 'string')
  ), 'struct');

$c = new XML_RPC_client($xmlrpc_path, $host, 80);
$appkey = new XML_RPC_Value($appkey, 'string');
$username = new XML_RPC_Value($user, 'string');
$passwd = new XML_RPC_Value($passwd, 'string');
$message = new XML_RPC_Message(
  'blogger.getUsersBlogs',
  array($appkey, $username, $passwd));
$result = $c->send($message);

if(!$result){
  exit('Could not connect to the server.');
} else if($result->faultCode()){
  exit($result->faultString());
}

$blogs = XML_RPC_decode($result->value());
$blog_id = new XML_RPC_Value($blogs[0]["blogid"], 'string');
$content = new XML_RPC_Value(
  array(
    'title' => new XML_RPC_Value($title, 'string'),
    'categories' => new XML_RPC_Value($categories, 'array'),
    'description' => new XML_RPC_Value($description, 'string'),
    'dateCreated' => new XML_RPC_Value(time(), 'dateTime.iso8601'),
    'custom_fields' => new XML_RPC_Value($custom_fields, 'struct'),
  ), 'struct');
$publish = new XML_RPC_Value(1, "boolean");
$message = new XML_RPC_Message(
  'metaWeblog.newPost',
  array($blog_id, $username, $passwd, $content, $publish));
$result = $c->send($message);

if(!$result){
  exit('Could not connect to the server.');
} else if( $result->faultCode() ){
  exit($result->faultString());
}

簡単ね!あとは自動でガンガン投稿するようにゴニョゴニョすれば万事快調.

イサム開発で使ったプログラミング等のTips

イサムの開発にあたって,いくつかの新しいテクニックを用いたので,新旧あわせて使ったテクニックを紹介したいと思います.

mod_rewriteでGETパラメータを変換

例えば,以下のようなURLを考えます.

http://4403.biz/ISAM/organization/NEC/

なんとなくパーマリンクっぽくて素敵ですよね.でも,この実体は以下のように処理したいと考えます.

http://4403.biz/ISAM/hoge.php?mode=organization&query=NEC

この変換をmod_rewriteで実現します.まぁ,Wordpressとかで使われている常套句ですね.mod_rewriteが有効な状態で,.htaccessに以下のように書きます.

RewriteEngine on
RewriteBase /ISAM/
RewriteRule "^(.*)/(.*)/$" "hoge.php?mode=$1&query=$2" [L]

簡単ね!ご存じだとは思いますが,これにGETパラメータがさらにくっつくような状況下では,QSAフラグも付けましょう.

hoge.phpでは受け取ったGETパラメータによって処理を振り分けたらいいと思います.これで実体を隠蔽しつつ,パーマリンクっぽいURLも提供できて,なんだかすごくいい感じです.クールURI!

mod_rewriteのBフラグ

上記の設定の後に,以下のようなアクセスを想定しましょう.

http://4403.biz/ISAM/organization/KDDI R&D Labs./

なんとなく上手くいかなさそうな気配がぷんぷんしますよね?実際にやってみると,このように展開されます.

http://4403.biz/ISAM/hoge.php?mode=organization&query=KDDI R&D_Labs_=

なんだか変なことになっている.紐解きましょう.GETパラメータがどうなっているかというと以下の通りです.

mode=organization
query=KDDI R
D_Labs_=

おい!って話ですね.問題点はR&Dの&をGETパラメータの接続詞と解釈してしまっています.解釈してしまっていますというか,それで正しいわけですが・・・.単純な解決策はURLエンコードです.しかし,そのためには,以下のようなアクセスを想定することになります.

http://4403.biz/ISAM/organization/KDDI%20R%26D%20Labs%2e/

こんなの恥ずかしくて見せられない!ということで,これをmod_rewrite中に実現したいわけですね.で,調べてみるとあるんですよ,これが.apache2.2.6以降らしいですが,Bフラグというものがあります.以下,引用.

B‘ (escape backreferences)
Apache has to unescape URLs before mapping them, so backreferences will be unescaped at the time they are applied. Using the B flag, non-alphanumeric characters in backreferences will be escaped. For example, consider the rule:
RewriteRule ^(.*)$ index.php?show=$1
This will map /C++ to index.php?show=/C++. But it will also map /C%2b%2b to index.php?show=/C++, because the %2b has been unescaped. With the B flag, it will instead map to index.php?show=/C%2b%2b.
This escaping is particularly necessary in a proxy situation, when the backend may break if presented with an unescaped URL.

mod_rewrite – Apache HTTP Server

簡単ね!というわけで,先ほどのRewriteRuleにBフラグを追加すると,こんなアクセスが来ても,

http://4403.biz/ISAM/organization/KDDI R&D Labs./

こんな風に渡されるので,

http://4403.biz/ISAM/hoge.php?mode=organization&query=KDDI%20R%26D%20Labs%2e

hoge.php側では$_GET[‘query’]をurldecodeしておけばいいですね.いい時代だね~.

memcachedの導入

インクリメンタルサーチでゴリゴリ検索させています.基本的にかなりの力業実装です.ですので,負荷を減らすためにキャッシュは重要になります.当初はMySQLのキャッシュ機能とAPCに丸投げしていたのですが,DBの更新が無ければ結果は不変なので,まるっとキャッシュしてしまえばいいのではないかと思ったので,memcachedしました.初挑戦です.

そもそもmemcachedとは何かといえば,以下のようなものだそうです.

Free & open source, high-performance, distributed memory object caching system, generic in nature, but intended for use in speeding up dynamic web applications by alleviating database load.

memcached – a distributed memory object caching system

ということで目的にピッタリです.で.基本的な使い方を確認しましょう.PHPではpecl::memcacheを使うのがいいのかな?似たものにpecl::memcachedもあります.よくわかりません.今回はmemcacheを使います.基本的な使い方は以下の通りです.

$mem = new Memcache;
$mem->addServer('localhost', 11211);
$val = $mem->get($key);
if(!$val) {
  //$valを作る作業
  $mem->add($key, $val, MEMCACHE_COMPRESSED, 3600);
}
$mem->close();

簡単ですね.これを応用して,イサムをキャッシュしまくります.方針としては,$keyをSQLクエリにして,$valをHTML出力文字列としています.つまりは,SQLクエリをキーにしてページフルキャッシュとほぼ同等です.これでキャッシュにヒットすればサックサクのはずです.

これをよくよく考えると,実行時間命なシステムでDBへの書き込みや更新がボトルネックになっている場合,とりまmemcachedにはき出しておいて,別プロセスで非同期にmemcachedから取り出してDBに格納するとかしてレイテンシを隠蔽できそう.そんなクリティカルなシステムを作ったことないですけどね.

エスケープとか

エスケープも別に珍しいことはしてなくて,strip_tagsやらmysql_escape_stringやらhtmlentitiesやらを使ってます.「エスケープは出力時に」という基本に忠実です.SQL文の構築はプレースホルダーを用いているので,そんなに変なことは起きないはずだと信じてます.攻撃しないで!

PHPの小ネタ

PHPはHTMLの中に直接スクリプトが書けるという実に変態な言語なので,様々な変態テクニックが駆使可能です.例えば,if文の途中でphp終了タグでぶった切って,HTMLを出力(というかそのまま表示)して,php開始タグで再びif文に復帰するとかいう常識的に考えられないような変態スーパーテクニックが利用可能です.可読性?なにそれ?誰が読むの?

それはそれとして,多少便利なものとしては,includeを用いたページ分割です.include命令によって別のphpファイルを読み込む(C言語の#includeのように)ことができるので,共通であるヘッダ部とフッタ部を別ファイルに分割することで,コード修正時の修正範囲を限定的にすることができます.ちなみに,これはHTMLヘッダ部でもできますので,かなり応用が利きますよ.

スーパーテクではありませんが,jQueryと組み合わせてajaxでインクリメンタルサーチやサジェストを実現しています.

情報セキュリティ学術研究マップ

本日未明,@akirakanaokaさんによって,情報セキュリティ学術研究マップ,通称イサムがリリースされました.

イサムってなに?

情報セキュリティの世界で、主に日本の研究者がどんな研究をしているかを検索できるサービスです。

基になっているデータは「暗号と情報セキュリティシンポジウム(SCIS)」の2001~2010年、「コンピュータセキュリティシンポジウム(CSS)」の1999~2010年、のプログラム情報です。

分野については現状では各シンポジウムのセッション名としています。

情報セキュリティ学術研究マップ

イサム(ISAM)はInformation Security Academic research Mapの略称です.SCIS2001-2010およびCSS1999-2010のプログラムを横断的に検索可能です.論文名,著者名,所属,分野(カテゴリ)に基づいた検索が可能となっています.

イサムへの貢献

イサムの実現においては,@akirakanaoka先生を中心に,@tohkiさんとともに私も協力させていただきました.

私の担当部分はフロントエンドで,DBへの投入とWebの実装をしました.主にプログラミングしました.大したことではないんですが,ポイントは以下の通りです.

  • HTML5
  • CSS3
  • jQuery
  • インクリメンタルサーチ
  • サジェスト機能(分野のみ)

このように自分がやってみたかったテクノロジーを満載にしてみました.技術の無駄遣いです.

イサムの今後

イサムは本日開催されるSCIS2011のナイトセッションにて発表される予定です.

イサムをどうぞよろしくお願いいたします.

イサムのプレスリリース

日本最大のセキュリティ系シンポジウムであるSCIS2011のナイトセッションにて@akirakanaokaさんが発表を行いました.発表の様子はYouTubeに公開されています.

2 / 212

Home > タグ > programming

アフィリエイト

Return to page top