wp-hatena 拡張版 1.1 リリースしました

今まで wp-hatena 拡張版は各エントリ(単体ページ)での利用を想定していたのですが、それ以外のページでも使えるように調整しました。

具体的には、単体ページ以外でも mixi チェックのボタンがきちんと動作するように修正しました(thanks @takenao さん!)。

DL:WordPress Plugins/JSeries » wp-hatena 拡張版

単体ページ以外での使用方法

とりあえず、詳しいことはいいから表示させたいよ!という方は以下のようにしてみてください。
※wp-hatena は表示させたい場所にコードを書いておくことで使うタイプのプラグインです。

新しいコード

単体ページ以外にも表示させたい場合はこちらを。面倒だったら単体ページもこちらで大丈夫です。

<?php global $wph; if(isset($wph)) {
    $wph->addhatena();  //表示させたいものを記述
}?>

よく分からなければ、こちらのほうで書いておけば間違いないです。

今までのコード

今後も単体ページではこのままのコードで表示できますので、今まで表示できてたページは変更不要です。

<?php if(isset($wph)) {
    $wph->addhatena();  //表示させたいものを記述
}?>

経緯

事の発端

@odyssey 拡張版を使っていて、タグというか、指定されたphpのコードを追加したのに、表示されないんです。。category.phpに入れたいのですが、それがまずいのかなぁ・・・と。すでに稼働中のサイトなので、あまり大胆にデバグすることもできず・・・。Wed Nov 09 04:35:50 via ついっぷる/twipple

@takenao うえつんが loop ファイルの中だと使えない、とか書いてましたが、その関係でしょうか…。 http://t.co/cQYiSxT3 include されるほうのファイルに書いてもうまく動かないようですね。Wed Nov 09 04:38:57 via Tween

むむむ、動かないらしい。なんでだろう。loop 内だとダメなのかな?エントリ個別ページで表示することしか想定していなかったけれど、それ以外でも使えるならそれにこしたことはないな~、ということで調べてみると、以下のようなことが分かりました。

  • wp-hatena.css は読み込まれている。→コンストラクタは動いてる(=プラグインはちゃんと読み込まれて動いてる)
  • if(isset… のところは、「$wph という変数があったら、この中身実行してね」という意味なのですが、そこから先が読み込めてない。変数 $wph が見当たらない状態になってる様子。

wp-hatena の仕組み

WordPress のプラグインは、プラグインを WordPress 本体に引っ張る hook を使っているものがほとんどです。(参考:プラグイン API – WordPress Codex 日本語版
ですが、wp-hatena はメイン機能(ブックマークボタン等を表示する機能)で hook を使っていません。※拡張版では css, js の読み込みにちらっと使っています。

理由をwp-hatena 本家作者ひろまささんの記事から引用すると…

作った当初は、自動でタイトルの横に入ればいいな~なんて考えていたのですが、冷静に考えると自由な場所に入れられたほうが便利だな、と考え今の形(使う方にテーマから呼び出してもらう)になっています。

hiromasa.zone :o) » wp-hatena にみるプラグインの作成方 – 前編 –』より引用

自動でソーシャルブックマークのボタンを挿入してしまうより、自分が好みの場所にコードを書いて使う方が便利じゃないかなーという、ことですね。

つまり、function.php などにソーシャルブックマークボタンを呼び出すためのオレオレ関数を作っておくぜ!ということの延長にあるタイプのプラグインということです。

function.php に書くことに比べると wp-hatena を使うほうが手軽に色々できますが、基本は同じ「変数を用意しておく」「それをテンプレート内で呼び出す」という二段階。

$wph を参照できるように

話は戻って…。変数 $wph が見つからない状態になっているようだったので、これをなんとかすればいけるはず、と考えました。

wp-hatena プラグインの一番最後で、$wph = & new WpHatena(); として、クラス WpHatena のオブジェクトを生成して変数 $wph に入れているので、それをもう一度書いてあげれば動くんじゃないかなーと思い、以下のようにして試してみました。

<?php $wph = & new WpHatena();
if(isset($wph)) {
    $wph->addhatena();  //表示させたいものを記述
}?>

動いたー!とりあえず、こうすれば動きますーとツイッターでお返事をしていたところ、まがりんから以下のようなツイートが。

@hibiki443 @takenao @uetsuhara @odyssey content.phpとかだったら、global宣言で解決するかも。Wed Nov 09 11:17:39 via Tween

global 宣言でいけるかもとのことなので、引き続き調べてみました。

根本的な原因と、WordPress テンプレートの流れ

まずは、PHP の変数について。

  • 変数は「その変数を参照することができる範囲」が決まっている。この範囲=スコープ。関数内=1 スコープ。
  • 普通は、関数の外からは関数の中の変数は参照できない(見つけられない)、関数の中からは関数の外の変数は参照できない。
  • 関数外の変数(グローバル変数)を参照したい場合は宣言が必要(グローバル宣言)

動かなかった原因は WordPress のテンプレートを読み込む仕組みに沿った呼び出し方をしてなかったからでした。
WordPress のテンプレートは大きく分けて 2 つ。

  1. 一番外側、外枠の指定のあるテンプレート、index.php や page.php など。これらは一番上のスコープ(グローバルスコープ)で処理され、プラグインで指定した変数や function.php で指定した変数をそのまま呼び出すことが出来る。
  2. 他のテンプレートから呼び出されるパーツ的なテンプレート、loop.php など。これはそれぞれ呼び出される時に使った関数内で実行されるので、1 とは違うスコープになる。違うスコープの場合、そのままではプラグインで指定した変数などの変数を呼び出すことができない。

テンプレートは全部同じスコープにあるー、と、深く考えずぼんやり思っていました…。

違うスコープにあるから変数を見つけられない、ということなので「違うスコープの変数を参照したいよ!」とグローバル宣言をすることで解決できるということに。表示させたいテンプレート内で 1 度、global $wph; としてグローバル宣言してあげれば OK。

<?php global $wph;  //グローバル宣言で $wph を参照できるように
if(isset($wph)) {
    $wph->addhatena();  //表示させたいものを記述
}?>

これで表示できるように(この記事の最初のほうで書いたコードと同じです)。そのスコープで 1 回グローバル宣言してあれば良いので、例えば、記事の最初と終わりの二カ所に表示させたい場合、二番目のほうは global $wph; を書かなくても大丈夫です。

とはいえ、記述するコードが変わると使い勝手が落ちますし、2 回グローバル宣言を書いても問題はないかなと思うので、いつも書いてもらう形にしておけば間違いなくて良いかなー。

こうやってちょっとずつプラグインが育っていくのだなぁ、と思いました。「よく分からないけれど、こうすれば解決する」という段階から、「原因が分かったうえで、解決方法を出せる」という段階にいけると、「そうだったのかー!」とちらばっていた事柄がつながって楽しいですね。

実は途中、global $wph; を <?php の外に書いていることに気がつかず、しばらく遠い目になったのですが…

@hibiki443 @takenao @jim0912 @uetsuhara 諦めたらそこで試合終了だよ(・×・)Wed Nov 09 13:43:18 via Tween

このツイートを見て、やり遂げなくてはー、と思いましたw かなり悩んだのに、しょぼしょぼなケアレスミスでした…T T

アドバイスくださったまがりん、記事にもまとめてくださっていたうえつん、応援してくださったおでさん、キッカケをくださったtakenaoさん、どうもありがとうございました!

長くなってしまいましたが、挿入したい場所に wp-hatena のコードを書いても表示できない状態だった方、よろしければお試しください :)