2006-04-25 Tue

ブログを引越ししました。新しいブログもよろしくお願いします。
Heartfield - What’s wrong about feeling good?

NP_Amazon|一覧表示を軽くする

とっても便利な Amazon アソシエイト活用プラグイン「NP_Amazon」ですが、月別アーカイブやカテゴリー一覧表示など、記事が多くなると表示に時間がかかってしまいます。1 時間おきに Amazon へ問い合わせをしているのがその原因だと思うのですが、それはルールなので仕方ありません*1。が、記事のタイトルしか表示しない場合も Amazon に問合せをするため、当サイトではカテゴリー一覧、タグ抽出、アーカイブ一覧など、多量の記事タイトルを表示する場合に結構な時間がかかっていました。細かいことを言えば、前後の記事や最近の記事、ランダムピックアップの中に該当するアイテム*2がある場合も同じように動作するので、表示速度に影響があるわけです。…まあ人気サイトだとひっきりなしにアクセスがあるのでほとんど影響ないのでしょうけど、当サイトのようにひっそりしているサイトでは結構困ったことです*3

この問題をずっと前からなんとかしたいと思っていたのですが、ソースを見ても「こりゃしょうがないわ…」と何度も諦めていました。ところが今日、ハッと閃き、タイトルのみを表示する場合は NP_Amazon を動作させないことに成功しました。…したと思います。

記事中に「<%amazon(asincode)%>」が記入されていた場合の処理は「event_PreItem」関数内で行われています。この関数自体は数行で終っていて、実際に Amazon に問い合わせる処理はすぐ下の関数「convertAsbn」が行っているようです。

下記の正規表現部分は NP_Footnote の機能を切るために半角スペースが入っています。ご注意ください。

function event_PreItem($data) {
 $preg_expr = "#<\%amazon\((.*?)\)%\>#i";
 $this->currentItem = &$data["item"];
 $this->currentItem->body = preg_replace_callback($preg_expr, array(&$this, 'convertAsbn'), $this->currentItem->body);
 $this->currentItem->more = preg_replace_callback($preg_expr, array(&$this, 'convertAsbn'), $this->currentItem->more);
}

修正メモがかなり膨大かつ分かりにくくなったので、とりあえず修正点を書きます。追記有

function event_PreItem($data) {
 global $currentTemplateName;

 switch ($currentTemplateName) {
  case "item":
   $preg_expr = "#<\%amazon\((.*?)\)%\>#i";
   $this->currentItem = &$data["item"];
   $this->currentItem->body = preg_replace_callback($preg_expr, array(&$this, 'convertAsbn'), $this->currentItem->body);
   $this->currentItem->more = preg_replace_callback($preg_expr, array(&$this, 'convertAsbn'), $this->currentItem->more);
   break;
  default:
   $preg_expr = "#<\%amazon\((.*?)\)%\>#i";
   $this->currentItem = &$data["item"];
   $this->currentItem->body = preg_replace($preg_expr, '', $this->currentItem->body);
   $this->currentItem->more = preg_replace($preg_expr, '', $this->currentItem->more);
   break;
}

まず「$currentTemplateName」という global 変数を呼び出します。すると、表示に使用されているテンプレート名を利用できるので「$currentTemplateName」が「item」だった場合は通常の動作をさせて、それ以外、例えば「itemex」「spitem」「index」とかとにかく「item」以外だった場合は処理を中止しています。多分ですが…「<%amazon(asincode)%>」を削除しています。

当サイトでは個別アイテムページには「item」という名前のテンプレートを使用しているので、他の名前を使っている場合やカテゴリーーに応じてテンプレートを変更している場合は「case "item":」の「item」を変更してください。

この修正をすると、以前 RSS 表示対策として書いた「NP_Amazon|Bloglines 対策」の修正は不要っぽいけど…どうなんだろう。

やはり不要ですね。この修正だけで RSS 対策ができます。

修正の軌跡

「event_PreItem」の処理は、記事の中に「<%amazon(asincode)%>」があったら「convertAsbn」にデータを渡すという感じ。これは NP_Amazon をインストールすると、記事を表示する時に必ず行われている処理。なぜなら「PreItem」を使ってるから。必ず行われるから別に記事の内容を表示しない時でもこの処理が発生してしまう。だったらタイトルのみ表示する時は別にこんなことはしなくていいよ、と条件をつければいい。どうやって「今はタイトルしか表示しないよ」と NP_Amazon に教えるのか? 記事の表示形式を決めるのはテンプレート。ここに「<%titel%>」「<%body%>」「<%more%>」とか書いて、思い通りの表示をするのが Nucleus の醍醐味。なので、記事全文を表示するテンプレートの場合だけ「convertAsbn」にデータを渡すように修正する。しかしその方法は不明。

NUDN - Nucleus Developer Network / Nucleus v3.2」を眺めていると「$currentSkinName」なる変数を発見。skin があるなら template もあるだろうと安易に「global $currentTemplateName;」と宣言。PreItem 関数の最後に「echo $currentTemplateName;」とすると見事にテンプレート名を表示。以前の改造「NP_Amazon|Bloglines 対策」を見て、if 文を追加。多分成功。どこかで switch の方が速いと書いていたのを思い出し、switch 文に書き換え。そして完成。

と思っていたら指定したテンプレート以外だと「DISALLOW(amazon)」と表示されてしまったのでさらに修正しました。

データを取得した日時を見ると、カテゴリー一覧やアーカイブ一覧を表示した時刻ではなく、個別の記事を開いた日時になっているし、「NP_Benchmark」の計測時間も短くなっているので多分思い通りの動作になっているはずなんですが、いまいち確信が持てません(笑)。というのも僕が根本的に PHP をまだまだわかっていないからなのですが。勘に頼る部分多すぎ(笑)。もっと根本的なところを理解できるようなりたいもんです。

  1. *1 - AWS の規約だと思います。
  2. *2 - <%amazon(asincode)%> を使用しているアイテム。
  3. *3 - せっかくきてくれた貴重な訪問者が表示の遅さに遭遇するので(笑)。

関連記事

Tag: /

2006-04-25 Tue / Category - Nucleus / Comment - 0 / TrackBack - 0

「NP_Amazon|一覧表示を軽くする」へのトラックバック

TrackBack URL:

「NP_Amazon|一覧表示を軽くする」へのコメント





このページの先頭に戻る

Copyright 2006 - Heartfield