ppBlog Notice: LINE 148 of log.php: Uninitialized string offset: 4

ppBlog Warning: LINE 112 of amazon_associate.php: file_get_contents(http: //ecs.amazonaws.jp/onca/xml?AWSAccessKeyId=AKIAIAAAF5TNOKUT32PA&AssociateTag=ppblog-22&ItemId=B000NJFUNU&Operation=ItemLookup&ResponseGroup=Medium%2CReviews&Service=AWSECommerceService&Timestamp=2024-10-05T21%3A01%3A54Z&Version=2009-06-01&Signature=TKcKC09M7wFITkIGZcVHELQn3sOoGxs2N7GcVIFUrtg%3D)

ppBlog official

アマゾンのProduct Advertising APIに対応させる

category-icon

 こんばんは。2009年8月15日からアマゾンのリンク作成用API(Product Advertising API, 旧称:AmazonアソシエイトWebサービス)が署名認証を含まないリクエストを一切処理しなくなりました。この影響で、ppBlogでの既存のアマゾンタグやアマゾン検索が動かなくなっています。なので、それに対応させるための書き換えを遂行しました。

 具体的な処理の流れは、もやし日記LinkIMHOLink が大変参考になりました。アマゾンサイトにある説明Link を一度読んで理解できる人はそういないだろうなぁ。

 このアマゾンのProduct Advertising APIですが、PHPのみで対応させるとなるとサーバー環境によっては実装が難しいかもしれません。基本的には、PHP5の環境でないと気軽に動きません。今や、PHP4の公式サポートも終了し、多くのレンタルサーバーではPHP5を提供していると思うので、さほど問題になることはないかも、とは思いますが。

 どうしてPHP5が必要かというと、アマゾンのこのサービスは、sha256Wアルゴリズムのハッシュを生成する必要があるからです。PHP5なら、hash_hmac関数Link が使えます。じゃ、PHP4な環境ではどうするか?もし、PHP4の環境でmhashライブラリーを組み込んでいるならOKです。このmhashライブラリー、非ウィンドウズなサーバー環境なら、最初から実装している気はします。ちなみに、自分のノートに構築したWindows下のXAMPPG環境では、mhashはデフォルトでは有効でなかったです(libmhash.dllを有効にすれば良いんでしょうけど)。

 この部分の処理は以下のようにしています。

 /* 
      PHP4でsha256ハッシュを生成するための処理。mhashが必須。
      RFC 2104 HMAC implementation for php.
      source:: http://www.php.net/manual/en/function.mhash.php
 */
if(!function_exists('hash_hmac')){ // hash_hmac()関数はPHP4にはない
 if(function_exists('mhash')){
  function sha256($data = ''){
   return bin2hex(mhash(MHASH_SHA256, $data));
  }
 } else $out .= '<p class="alert">mhashライブラリーのサポートがないようです。サーバーの管理者にお問い合わせを。</p>';

 function hash_hmac($algo, $key, $data, $raw_output = FALSE){
  $b = 64; // byte length for sha256
  if(strlen($key) > $b){
   $key = pack("H*", $algo($key));
  }
  $key  = str_pad($key, $b, chr(0x00));
  $ipad = str_pad('', $b, chr(0x36)); $ipad ^= $key;
  $opad = str_pad('', $b, chr(0x5c)); $opad ^= $key;
  $hmac = $algo($opad . pack("H*", $algo($ipad . $data)));
  if($raw_output){
   return pack("H*", $hmac);
  } else return $hmac;
 }
}

 ppBlog独自の既存のアマゾンタグを修正しないといけないかなぁという懸念もあったのですが(そうすると過去のログを修正する必要がある)、その必要なかったです:) この新しいAPIに対応させるには、これから添付するamazon_associate.phpmodules/amazon.inc.phputils.phpとで既存のやつを上書きすれば良いです。その後、管理画面の「各種ツール」→「アマゾンアソシエイト」で、新たに取得したアクセスキーとシークレットキーなどの設定をします。最初は、「変数が設定されていないよー」といったppBlog Noticeが出るかもしれませんが、設定をすすめていけばOKです。そのスクリーンショットを載せときますね。

amazonAPI
規定のジャンルの指定も出来るようにしてます。

 この画面にもあるように、従来のアソシエイトタグ(ppblog-22とか。トラッキングID)だけでは、もはや動きません。アマゾンAPIを利用されたい方は、アマゾンのサイトLink で、このAPIを利用するための2つのキーを入手して下さい。

 ちなみに、この新しいAPIに対応したデモサイトを作りました。基本的には、amazon_associate.phpでやってる処理と同じです。

 →Amazon Product Advertising APIのデモ http://p2b.jp/demo/aws.phpLink

 動作確認も兼ねて、この記事でアマゾンの商品を紹介しておきます。Nespressoのエスプレッソマシーンは、日本にいるときも使っていたのですが、フランスに来て暫くして、よりコンパクトなこれを買いました。ユーロだと安かったなぁ。使っているのはワインレッド色のやつですが。カプセル方式は、楽チンで良いです。

— posted by martin at 02:22 am   commentComment [0]  pingTrackBack [0]

記事アクセスランキング修正版

category-icon

 こんばんは。数個前の記事で紹介した記事アクセスランキングですが、個別記事にアクセスした際には、表示されていませんでした。これは、$RANKINGという変数のグローバル宣言をしていないためという凡ミスでした。。なので、それを修正したutils.phpを添付しておきます。また、現状では、「最近のエントリー」で表示される記事数(つまり定数RECENT_ENTRIESの同じ数がリスト表示されますが、showRanking関数のこの部分を好きな数字に変えることでリストの表示数をコントロール出来ます。

 尚、別件ですが、はてなのブックマークエントリー数を取得するAPIが変更になったLink ようで、現状ではPHPのエラーが出るかと思います。これは、ソーシャルブックマークのアイコン表示を有効にしている場合です。これの対策としては、utils.phpに記述してある$SBM_LIST変数内を修正する必要があります。具体的には、この中の'はてなブックマーク'の部分、

'b.hatena.ne.jp/entry/json/?url='
'api.b.st-hatena.com/entry.count?url='
に書き換えます。

— posted by martin at 09:35 am   commentComment [3]  pingTrackBack [0]

 

Google AJAX Feed APIを利用したスライドショー

category-icon

 こんばんは。前回の書き庫コメントでアップロードした画像のスライドショーの話が出ていたので。

 ブログのサイドバーでスライドショーを見せるブログパーツは結構あると思いますが、良く見かけるのはAdobeのFlashを用いて表示させる方法。これは純粋にJavaScriptを使うよりは、凝った演出が出来る傾向にあります。もっとも、最近はモダンなブラウザではCanvas要素Gをサポートしているので、JavaScriptだけでも凝った演出が可能になってますけど(ppBlogでは、写真を回転させたりして表示できますが、この部分でCanvasを使っています)。

 単なる好みの問題ですが、サイドバーでスライドショーを見せる際に演出に凝りまくるのは、あまり好きでありません(特にFlash系)。なので、スライドショーを見せるにしてもJavaScriptのみで動くシンプルなものが良いなぁ、と思いました。スクリプトは自前で用意したいところですが、画像切り替えのアルゴリズムなどを考えるとはまりそうなので、ここは既知のJavaScriptライブラリーを使うことにします。

 で、Google AJAX API Link が良さそうでしたので、これを使ってスライドショーを付けてみました。Googleで、スライドショーそのもののスクリプトを公開しているLink ので、それを利用するだけです。実際のデモは、http://p2b.jp/demo/slideshow.htmlLink  あるいは http://martin.p2b.jp/index.phpLink で確認出来ます(3paneのテーマであれば右側に表示される)で確認できます。

 早速ですが、簡単な設置手順を記しておきます。

  1. mediaRSSファイルが必要なので、それを作成するadmin.phpmodules/mrss2.inc.phpをゲット。
  2. 管理画面の「各種ツール」に「MRSSの作成 2」というメニューがあるので、それを選択。これでmediaRSSが作成される。
  3. 表示させたいテーマのtemplate.phpに必要なJavaScript関連の記述をする。

 基本的にはこれで足ります。template.phpに記述するJavaScriptですが、先に挙げた小生のサイトでは、まず以下のようにして動作に必要なファイルをGoogleのサーバーから外部スクリプトとして呼び込んでいます。

 <script type="text/javascript" src="http://www.google.com/jsapi?key=(AJAX APIのキー)"></script>
 <script src="http://www.google.com/uds/solutions/slideshow/gfslideshow.js" type="text/javascript"></script>

AJAX APIのキー指定ですが、これはなくても動きますが、グーグルのサイトで簡単に入手出来るLink ので手に入れておくと良いでしょう。

 この2つのスクリプトを通じて、予め用意したmediaRSSファイルを読み込んで、画像を順次表示させていく訳ですが、mediaRSSファイルを手書きで用意するのは大変なので、こういうものはppBlogに作らせましょう(手順1, 2)。ppBlogで生成されるmediaRSSは、具体的にはhttp://martin.p2b.jp/feeds/mrss.xmlLink のような感じになります。

 このmediaRSSファイル読み込み時に起動する呼び出し関数は、以下のような記述です。グーグルのサイトにあるサンプルコードとほぼ同じです。

function load(){ // mediaRSSファイルを読み込んだ際のコールバック関数
  var src = "http://martin.p2b.jp/feeds/mrss.xml"; // 読み込むRSSファイルを指定
  var options = {
    displayTime: 3000,  // 一枚あたりの画像表示時間(ミリ秒)
    transistionTime: 1000, // 画像切り替えのフェードアウト・フェードインの時間(ミリ秒)
    scaleImages : true, // 指定したサイズに合わせて画像を縮小させるかどうかのオプション指定
    linkTarget : google.feeds.LINK_TARGET_BLANK // 画像をクリックした際に新しいウィンドウ(タブ)でリンク先を開くか
  };
  new GFslideShow(src, "slideframe", options); // slideframeというID名を持つ要素に対して発動
 }
 google.load("feeds", "1");
 google.setOnLoadCallback(load);

これに対するHTMLの記述は以下のような感じです。これもtemplate.php内の記載になります。

 <div id="slideshow" style="margin: 60px auto 30px auto; width: 120px; height: 150px; background: url(theme/3pane/Images/slide-frame.jpg) no-repeat; padding-top: 30px;">
  <div id="slideframe" style="width: 100px; height: 100px; margin: auto; position: relative;"></div>
 </div><!--#slideshow-->

ここでは、インライン形式のスタイルシート指定にしていますが、勿論スタイルシートのCSSファイルで指定しても構いません。設置の参考にするには、上に挙げたデモサイトが分かりやすいかと思います。

 尚、このスライドショーは、マウスが画像に載ると、そこで一時停止します(これはデフォルトの動作)。で、そのままクリックするとその画像が含まれる記事にリンクするようになっています(これはmediaRSSの内容による)。

 ppBlogに組み込めるように、admin.phpとmodules/mrss2.inc.phpを添付しておきますね。

 参考リンク: http://www.google.com/uds/solutions/slideshow/reference.htmlLink

添付ファイル: admin.phpattachedIcon  mrss2.inc.phpattachedIcon 

— posted by martin at 12:17 am   commentComment [0]  pingTrackBack [0]

作成ページでPHPが通るようにしたい

category-icon

 こんばんは。昨日に引き続き。

 ppBlogでは、ブログのエントリーとは別に自由にページを作成することが出来るので、いわばCMSGのような使い方も可能です。このページ作成機能ですが、以前から改善したいなぁと思っていたことがありました。それは、作成したページの中に記述したPHPがスクリプトとしてちゃんと動作するということです。

 現状では、例えば、以下のような記述をしてページを作成してもそのまま書いた文字列が出力されてしまいます。

<?php
 echo "Bonjour à tous!"; // やぁ、みんな!
?>

上の記述は、以下のようになる。

echo "Bonjour à tous!"; // やぁ、みんな!
?>

 ページ作成画面でPHPスクリプトを自由に記述できれば、PHPに慣れた方なら色んなことが出来るようになります。なので、そうできるようにしてみましょう。ppBlogでは、作ったページは、単なるテキストファイルとして、pagesディレクトリに保存され、それをmodules/pages.inc.phpを介して、HTMLとして出力されます。なので、pages.inc.phpモジュールをいじります。具体的には、このファイルの中で定義されているoutputPage()関数に手を加えれば良いです。

 流れとしては、テキストファイル中に書かれてあるPHPタグ<?php・・・?>があれば、その中身をeval関数で評価、その結果を保持しておく。eval関数はその場ですぐに評価されるため、それがHTMLとして出力されるのを防ぐために、出力のバッファリングを有効にしておく、ということです。簡単に実装出来そうですね。以下のような記述でいけるかと思います。

if(preg_match_all('{<¥?php(.+?)¥?>}s', $page, $mt)){ // PHPタグを含むなら
  $BUFF = array(); // 評価した結果を保存する入れ物を用意しておく
  ob_start(); // 出力のバッファリングを有効に
  $length = count($mt[0]);
  for($i = 0; $i < $length; $i++){
   $php = $mt[1][$i]; // 実行させたいPHPスクリプトの中身
   if(eval($php) === FALSE){ // PHPのパースエラーなら
    $BUFF[] = "ppBlog warning: parse error!";
   } else $BUFF[] = ob_get_contents(); // きちんと評価されれば、その結果を取得
  }
  ob_end_clean();
 }

 ポイントは、ob_start関数とeval関数の組み合わせです。その際に、eval関数の返り値は、パースエラーならFALSEを返すけど、きちんと評価されれば、ob_get_contents関数で補足可能ということですかね。

 実際には、これ以外の微調整が必要ですが、それも反映させたPHP記述が有効になるpages.inc.phpを添付しておきます。既存のやつを上書きして問題ないです。

 と、これを書いている途中で思いついたのですが、ppBlogでは、[style]...[/style]の形式で、その記事だけに適用させるスタイルシートを指定出来ますが、これもページ作成画面でも指定出来るようにしました。このサイトで「人気記事ランキング」というページを作りましたが、そのソースは以下のようになってます。これをそのままページ作成画面のテキストエリアに貼り付ければOKです。

<h2>人気記事ランキング</h2>
<?php
echo '<ol>'.NL;
echo showRanking(); // utils.phpで定義している独自の関数も使える!
echo '</ol>'.NL;
?>

[style]
h2 { color: slateblue; margin: 1em auto 2em auto; }
ol li span {
 background: pink; font: bold 12px Arial; color: navy; padding: 2px 3px;
}
ol {
 list-style-type: decimal;
 width: 480px; margin: auto;
}
[/style]

 コメントにもありますが、utils.phpで定義している関数も使えるので色々と応用が利きそうです。ちなみに、上のスタイルシートの指定で、実際には以下のように、div.page-boxが自動的に付加された形で出力されます。

 <style type="text/css">
  div.page-box h2 { color: slateblue; margin: 1em auto 2em auto; }
  div.page-box ol li span {
   background: pink; font: bold 12px Arial; color: navy; padding: 2px 3px;
  }
  div.page-box ol {
   list-style-type: decimal;
   width: 480px; margin: auto;
  }
 </style>

 スタイルシート指定も有効するには、utils.phpもちょいと書き換えが必要です。これも添付しておきます。最近のバージョン(1.7-1.8)であれば、既存のを上書きしても特に動作に問題はないかと思います(いつでも元に戻せるように元のutils.phpのバックアップはとっておいて下さい)。


— posted by martin at 06:55 am   commentComment [3]  pingTrackBack [0]

各記事の閲覧数ランキングを表示させたい

category-icon

 こんばんは、久しぶりにmartinです。

 フォーラムの方で、「記事の表示回数と順位の表示は出来ないでしょうか?Link 」というエントリーがあって、ちょっとプログラミングがしたくなったのでとりあえず書いてみました。このサイトで、テーマをBasicにすれば、左側のサイドバーに「人気エントリー」というのが表示されていると思います。

 基本的には、utils.phpをいじることで実現できます。utils.phpの538行目あたりに以下の記述を追加しました。閲覧数を記録するファイル(ranking.ini.php)はownerディレクトリに作るとします。

 if(!ADMIN && $UID != ''){ // 閲覧数ランキング用
  if(is_file(($ranking = OD.'ranking.ini.php'))){
   include_once $ranking; // これで$RANKING配列をゲット
   $hit = preg_grep("/(¥d+¥t$UID¥t.+?)/", $RANKING);
   if(empty($hit)){
    array_push($RANKING, "1¥t$UID¥t$pm_link¥t$_title");
    rewrite_ini($ranking, $RANKING);
   } else {
    $ix = array_keys($hit); $ix = $ix[0];
    list($count,) = explode("¥t", $RANKING[$ix], 2);
    $RANKING[$ix] = (++$count)."¥t$UID¥t$pm_link¥t$_title"; // ヒットした数の更新
    $RANKING = array_slice($RANKING, 0, 100); // とりあえず100件も登録すればOKだろう
    rsort($RANKING, SORT_NUMERIC); // 大きい順にソート
    rewrite_ini($ranking, $RANKING);
   }
  } else rewrite_ini($ranking, '', '$RANKING'); // 記録保持ファイルがないなら作成
 }

 テーマファイルのtemplate.phpには新たな変数%_RANKING:1:人気エントリー:1_%を用意しておきます。具体的には以下のような感じ。つまりrankingという新たなIDが加わります(pprankingの方が良いかなぁ)。

<div id="ranking">%_RANKING:1:人気エントリー:1_%</div><!--#ranking-->

 そして、この変数を変換する関数を用意しておきます。

function showRanking(){
 if(is_file(($ranking = OD.'ranking.ini.php'))){
  include_once $ranking;
  if(!empty($RANKING)){
   $h = NL;
   foreach ($RANKING as $i => $r){
    if($i >= RECENT_ENTRIES) break; // 表示させる数はエントリー記事の表示数と同じ設定にしておく
    list($count, $uid, $pmlink, $title) = explode("¥t", $r, 4);
    $h .= '    <li><a href="'.$pmlink.'" title="'.date('Y年n月j日の投稿', $uid).'">'.$title.'</a> <span title="閲覧数">'.$count.'</span></li>'.NL;
   }
   return $h;
  }
 }
}

 後は、テーマファイルのCSSファイルもちょいといじって出来上がりです。とりあえず、この改造を施したutils.phpとBasicテーマのtemplate.php及びCSSファイルを添付しておきますね。

添付ファイル: template.phpattachedIcon  basic.cssattachedIcon  utils.phpattachedIcon 

— posted by martin at 05:53 am   commentComment [6]  pingTrackBack [0]

T: Y: ALL: Online:
Created in 0.7851 sec.
prev
2024.10
next
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31