Facebookアプリで「HTTPS+OAuth2.0」の利用義務付けが始まります&setAutoResize()が使えなくなります
Facebookアプリで「HTTPS(SSL)+OAuth2.0」の利用義務付けが始まることと、setAutoResize()が使えなくなることについてのお知らせです。
1.「HTTPS+OAuth2.0」の利用義務付けについて
2011年5月に「Facebookアプリ「HTTPS+OAuth2.0」の利用を義務付けへ」でお伝えしたとおり、2011年10月1日よりFacebookアプリはHTTPS(SSL)とOAuth2.0の利用が必須となります。
HTTPSに対応するには、App on Facebook」の「Secure Canvas URL:」と「Page Tab」の「Secure Page Tab URL:」に「https://」で始まるURLを設定します。

設定していないと、アプリを保存するときに次のような警告が表示されます。

JavaScriptでOAuth2.0に対応する方法は、「FacebookのJavaScript SDKがOAuth 2.0サポート」を参照してください。
2.setAutoResize()について
Facebookアプリでスクロールバーを表示しないための手段としてsetAutoResize()を使っているケースが少なくないと思われます。当ブログでも以下の記事で解説しています。
このsetAutoResize()が2012年1月1日より利用できなくなります、とFacebook開発者ブログでアナウンスされています。
Platform Updates: Operation Developer Love

記事では「setAutoResize()はsetAutoGrow()にリネームしてください」と書かれています。setAutoGrow()はすでに使えます。
ちなみにリネームの理由は次の通りです(間違ってたらすいません)。
setAutoResize()が正しく動作しないケースがあり、バグを修正したが、高さを正しく縮めることが難しいという結論に達しました。よって機能を正しく説明するためにsetAutoGrow()に変更します。正しく動作しない場合は、FB.Canvas.setSize()の利用を推奨します。
要するに「高さを縮めることが難しいので、高さを伸ばす意味の関数に変更します。この関数を使ってスクロールバーが表示される場合は代替手段を利用してください」ということみたいです。
問題なく動作している場合は単にリネームするだけですので、特筆すべきことはありませんが、ブログに掲載されているサンプルをこちらでも掲載しておきます。青色が変更部分です。
<html>
<head>
<title>FB.Canvas.setAutoGrow Example</title>
</head>
<body style="margin:0; padding:0; border:0; background-color:#555555;" >
<div id='fb-root'></div>
<script src="http://connect.facebook.net/en_US/all.js"></script>
<script type="text/javascript">
FB.init({
appId : 'YOUR_APP_ID',
oauth : true,
});
FB.Canvas.setAutoGrow();
function growSize() {
var height = Number(
document.getElementById('myContent').style.height.split('px')[0])
+ 100;
document.getElementById('myContent').style.height = height + 'px';
}
</script>
<div id="myContent" style="background-color:#FF0000; height: 100px;">
<input type="button" value="Grow!" onclick="growSize();"/>
</div>
</body>
</html>
サンプルの動作は「小粋空間」Facebookページの「setAutoGrow」タブから確認できます(そのうち削除します)。
Firefox8をインストールしてみた
巷ではFirefox7の話題で盛り上がってますが、PCには早くもFirefox8(Aurora)のベータ版をインストールしました。Firefox7の新機能については「Firefox7をインストールしてみた」をご覧ください。

Firefox8は、Firefox7のリリースと同時にベータ版が公開され、Firefox8の機能が確定しています。Firefox8のリリースは2011年11月8日のようです。
2011.11.08 予定通りFirefox8がリリースされました。
Firefox8では主に以下の改善が行われます。
- アドオンの管理機能が強化
- タブを選択するまで読み込まない設定を追加
- タブの並べ替えや分離の操作性を改善
- デフォルトのサイトアイコンを変更
- 使用メモリの削減
- menu要素でコンテキストメニューを定義
- innerHTML()よりも速いinsertAdjacentHTML()をサポート
以下、「Firefox 8 の主な新機能を紹介します」の記事を元に、改善内容を紹介します。
1.アドオンの管理機能が強化
Firefox8からは、外部プラグラムがアドオンをインストールする時にはユーザに確認するようになります。デフォルトでは無効化する設定になっています。
下のスクリーンショットはFirefox8立ち上げ直後のアドオン画面です。ベータ版のための「Feedback」以外は無効になっています。
2.タブを選択するまで読み込まない設定を追加
起動時のオプションから「前回終了時のウィンドウタブを表示する」を選択したときに、「タブを選択されるまでページを読み込まない」を設定できます。
再起動時には、選択しているタブはページ読み込みまで行われ、それ以外のタブはタブ部分のみ表示されます。
他のタブのページの読み込みは、タブ選択時に行われます。
3.タブの並べ替えや分離の操作性を改善
Firefox8ではタブの移動で空いたスペースに残りのタブが詰まる様子がアニメーション表示されるようになります。
タブを横に移動した状態
![]()
また、タブバーから外れた位置にドラッグすれば、タブバーからも削除され、サムネイルがに別ウィンドウとして分離します(Firefox7まではタブバーから削除されず、半透明のサムネイルで表示)。
タブをタブバーから外れた位置にドラッグ

4.デフォルトのサイトアイコンを変更
新しいタブを開いたとき、アイコンがないことを表す四角い点線が表示されます。
Firefox7

Firefox8

5.使用メモリの削減
Firefox7に引き続き、Firefox8でもメモリ削減が行われます。
Firefox 7 では大幅な使用メモリ削減を実現しましたが、HTML5 の <video>, <audio> 利用時に使用するスレッド数を削減したり、メモリの確保方法を改善したりすることで、Firefox 8 でも引き続きメモリ使用量の削減が行われています。
6.menu要素でコンテキストメニューを定義
Firefox8では他のブラウザに先駆けてmenu要素をサポートし、Webアプリ独自の右クリックメニューを定義できます。
7.innerHTML()よりも速いinsertAdjacentHTML()をサポート
insertAdjacentHTML()はInternet Explorer 4で最初に実装され、HTML5標準に含められたメソッドです。innerHTMLプロパティと同様、HTMLでマークアップされた文字列を渡して新しい要素を挿入できます。
サンプル
<div id="foo">foo</div>
<script>
ele = document.getElementById('foo');
ele.insertAdjacentHTML('AfterEnd', 'bar');
</script>
第1パラメータに挿入位置、第2パラメータに挿入テキストを設定します。第1パラメータの意味は次の通りです。
- BeforeBegin:エレメントの直前にテキストを挿入
- AfterBegin:エレメントの開始位置の直後にテキストを挿入(エレメント中の全てのコンテントよりも前に挿入)
- BeforeEnd:エレメントの終了位置の直前にテキストを挿入(エレメント中の全てのコンテントよりも後に挿入)
- AfterEnd:エレメントの終了位置の直後にテキストを挿入
8.ダウンロード
Firefox8は以下のリンクからダウンロードできます。
2011.11.09
Firefox8のリリースに伴い、記述を一部修正しました。
Movable Typeのカスタムフィールドに入力した複数のブログ記事IDからブログ記事リストを出力する
Movable Typeのカスタムフィールドに入力した複数のブログ記事IDからブログ記事リストを出力するカスタマイズを紹介します。
MTQで質問がありましたので、本エントリーで情報展開します。
1.カスタマイズイメージ
カスタムフィールド「ブログ記事ID」を作成します。種類は「テキスト」、テンプレートタグは「MTEntryIDs」とします。

ブログ記事編集画面に表示されたカスタムフィールド「ブログ記事ID」に、ブログ記事ページに表示したいブログ記事のIDをカンマ区切りで設定します。

ブログ記事を保存すれば、該当のブログ記事ページに、カスタムフィールドに入力したブログ記事IDに対応するブログ記事のリストを出力します(赤枠部分)。
以下、カスタマイズ方法を順を追って解説します。
2.Splitプラグインのインストール
以下のリンクよりSplitプラグインをダウンロード・インストールします。
Splitプラグインは、Perlのsplit機能をグローバルモディファイアとして提供します。
次のサブテンプレートは、変数fooに設定した「a,b,c」という値をカンマで区切り、「a」「b」「c」を配列変数barに設定するサンプルです。
<mt:setvar name="foo" value="a,b,c" />
<mt:getVar name="foo" split="," setvar="bar">
<mt:loop name="bar">
<mt:getVar name="__value__" /><br />
</mt:loop>
このサブテンプレートの出力結果は、
a
b
c
となります。
3.テンプレートの修正
次のようなサブテンプレートをブログ記事アーカイブに追加します。
<mt:if tag="EntryIDs">
<h2>関連ブログ記事</h2>
<$mt:EntryIDs split="," setvar="entry_ids"$>
<mt:loop name="entry_ids">
<mt:if name="__first__">
<ul>
</mt:if>
<mt:Entries id="$__value__">
<li><a href="<$mt:EntryPermalink$>"><$mt:EntryTitle$></a></li>
</mt:Entries>
<mt:if name="__last__">
</ul>
</mt:if>
</mt:loop>
</mt:if>
サブテンプレートの仕組みは次の通りです。
まずMTIfタグでMTEntryIDsタグの値の入力有無を判定し、入力がある場合はMTEntryIDsタグの値をsplitモディファイアで分割し、配列変数entry_idsに設定します。ブログ記事IDがひとつだけの場合も配列に設定します。
その後、MTLoopタグで、配列の値をひとつずつ取り出し、MTEntryタグのidモディファイアに設定することでブログ記事情報を取得します。
インデックステンプレートに表示したい場合は、次のように全体をMTEntriesタグで括ってください。
<mt:Entries>
…(元のブログ記事情報を出力)…
<mt:if tag="EntryIDs">
<h2>関連ブログ記事</h2>
<$mt:EntryIDs split="," setvar="entry_ids"$>
<mt:loop name="entry_ids">
<mt:if name="__first__">
<ul>
</mt:if>
<mt:Entries id="$__value__">
<li><a href="<$mt:EntryPermalink$>"><$mt:EntryTitle$></a></li>
</mt:Entries>
<mt:if name="__last__">
</ul>
</mt:if>
</mt:loop>
</mt:if>
</mt:Entries>
あとはブログ記事編集画面のカスタムフィールドに、表示させたいブログ記事IDを入力してください。
4.注意事項
ブログ記事数が多く、カスタムフィールドに大量のブログ記事IDを設定すると再構築時のパフォーマンスに影響が出る場合があります。
PHPやPerlで変数の記号に「$」が使われる理由
PHPやPerlで変数を定義するとき、当たり前のように先頭に「$(ドル/ダラー)」をつけていますが、ふと、
「変数の前に付ける記号はなぜ『$』なんだろう?」
と思い立ち、そんなことはものの本に書かれているのかもしれませんが、ネットで調べてみました。
ちなみにPerlで「$」を使うのはスカラ変数だけです。
1.「$」はBASIC言語から使われている
BASIC言語では変数の型で文字列を表すときに、次のように「$」を使っています。ただし変数の前ではなく後につけています。
10 READ A$
20 READ B$
30 C$=A$+B$
40 PRINT C$
また「『$』はBASICの名残で使っているようです」という記事をみつけました(ただしVBの話として)。
2.「$」は「ストリング」?
仮にPHPやPerlなどがBASICの名残で「$」を継承していると仮定しても、なぜBASICでは「$」を使っていたのでしょうか。
調べていると、Wikipediaの「Dollar sign」の解説の中に次のような記述がありました。
$ was used for defining string variables in older versions of the BASIC language ("$" was often pronounced "string" instead of "dollar" in this use).
推測の域を超えませんが、「$」という記号は縦棒がなければ「S」になるので、BASICの時代には「$」は文字列(String)を意味する記号として使われていたのかもしれません。
Perlの場合はスカラー(Scalar)の「S」として使っているのかもしれません(推測で書いてます)。
ということで明確な情報が得られていないので、情報お待ちしています。
2011.10.16追記
オライリー「初めてのPerl第5版」のP53に、「Larryの主張は、$calar,@rrayの意味で定義している」旨の記述がありました。
3.Perlの「@」や「%」の由来は?
話がそれますが、Perlの配列変数を示す「@」は「a」に似ているので「Array」を意味しているのかもしれません(これも推測です)。
また、ハッシュ変数を示す「%」は、簡単なハッシュ関数で割り算を利用した余りを使うので、その演算子を示す「%」からきているのでしょうか(もちろん推測です)。
こちらも情報お待ちしています。
4.参考サイト
1分で分かるFacebookタイムラインの使い方
Facebookのタイムラインの表示がなんだか分かりにくいという方へ。実際にあれこれ操作してみて、気がついた範囲で紹介します。
1.真ん中の上下に伸びている線は?
真ん中の上下に伸びている線(赤枠部分)は「時間軸」です。一番下が生まれたとき、一番上が現在です。
また任意の位置で線をクリックすれば、クリックした時間軸に遡って記録を記すことができます。これで過去の記録をFacebookにどしどし投稿できます。

もちろん日付も指定可能です。

2.左右のボックスは?
2カラムレイアウトのような感じでレイアウトされている箱はFacebook上のアクション(アクティビティ)で、時間軸からのふきだしという形で左右に分けて表示されています。
ボックスにマウスをのせると右上にアイコンが表示されます。

左が投稿を目立たせたい場合にクリック。右はタイムラインの表示や投稿の削除を行うときに使います。以前のプロフィール画面では、自分の投稿を削除したい場合はウォールから行えましたが、新しいフォーマットではこのアイコンで削除するようです。

★アイコンをクリックしたアクションは、左右に横断して表示されます(下)。また、投稿時に「ライフイベント」を選択した場合も大きく表示されます。
時間軸からのふきだしになっていないボックスは友達や「いいね!」をしているFacebookページ、写真などのエリアになるようです。
3.右上の年月表示は?
月または年の部分をクリックすれば、月または年単位でFacebook上のアクションを参照できます。

4.ウォールに投稿するには?
これは見てのとおり、左上のフォームから投稿できます。1項の投稿フォームと同じで、最新の時間軸からのふきだしとして表示されています。

投稿方法は「Facebookのウォール投稿方法が変更」と大体同じですが、「クエスチョン」がないのと、イベント(仕事・結婚・子供 etc.)について書くときのアイコンが5つ追加されているようです。
5.プロフィールを更新するには?
上部にある「基本データを編集」をクリックすればプロフィールの編集画面に移動します。

6.上部にある「アクティビティを見る」のリンクは何?

「アクティビティを見る」クリックすると、Facebook上のアクションを時系列に表示する画面(アクティビティログ)に移動します。
この画面では、アクティビティ単位にタイムラインの表示方法や公開範囲を指定できます。
公開範囲の指定

タイムラインの表示・非表示など

7.プレビュー
プレビュー機能を使えば、他のユーザーから自分のタイムラインがどのように見えるかを確認することができます。
右側にあるプルダウンメニューから「プレビュー」をクリック。

これで友達以外(フィード購読者含む)のユーザーへのプレビューが確認できます。
友達になっているユーザーからの見え方を確認するには、上部のテキストフィールドに友達(フィード購読者含む)の名前を入力。

これで友達ユーザーのプレビュー画面が表示されます。
8.ノート・フィード購読・アプリ追加など
ノートの投稿・フィード購読・アプリの追加などは、上部右側にあるアイコンをクリック。

これで表示エリアが拡張されて、ノートの投稿・フィード購読・アプリの追加が行えます。
Facebookタイムラインの利用方法
Facebookの新機能、タイムラインを使ってみました。
注:この記事は、タイムラインが正式公開される2011年10月2日までの話です。
タイムラインの使い方については「1分で分かるFacebookタイムラインの使い方」をご覧ください。
この機能を利用することで、プロフィールのページが下のスクリーンショットのようなレイアウトに切り替わります。
タイムラインは現在Open Graphのデベロッパー向けのみに公開されているようで、タイムラインを見る方法がTechCrunchで公開されています。
ということで、記事の説明を日本語向けにかみくだいて説明します。既存のアプリにOpen Graphを設定したあとに別のアプリを作り直してOpen Graphを設定した手順なので、初回と操作が異なるかもしれません。
タイムライン利用方法
タイムラインを利用するには、ダミーアプリを1つ作ります。アプリのページで「Create New App」をクリック(初めて作る場合はその前に許可画面が表示されると思います)。

適当なアプリ名とネームスペースを入力し、「I Agree~」をチェックして「続行」をクリック。ネームスペースに数字は使えません。
セキュリティコードを入力して「送信」をクリック。
作成アプリの編集画面が表示されるので「Open Graph」をクリック(この部分はTechCrunchの記事と説明が異なるので、別の画面が出るかもしれません)。

「People can」の右に任意の文字列(ここではread)、その右のセレクトボックスから任意のオブジェクト(ここではbook)を選択して「スタート」をクリック。
「Edit your Action Type」の下の方にある「Save Changes and Next」をクリック。同じようにEdit your Object Typeで「Save Changes and Next」をクリック(実験したときはスキップされました)。TechCrunchの記事では任意の項目を書き換えるように指示されています。

「Create an Aggregation」の下の方にある「Save and Finish」をクリック。

設定が完了するとこのような画面になります。

少し待ってから自分のウォールに移動すると次のような画面が表示されるので、「今すぐ利用」をクリック。

これで自分のプロフィールページに移動すると、タイムラインが表示されると思います。公開したい場合はページ上部に表示されている「今すぐ公開」をクリック。

PDFを拡大縮小せずに印刷する方法
毎年1回行われるコンサートのプログラム印刷を毎年請け負ってます。プログラムは数百枚印刷するため、家で印刷した原稿を「フェデックスキンコーズ」でコピーすることにしています。
今年は、プリンタが古いせいか原稿が鮮明に出力されなくなり、キンコーズのセルフプリントを利用して原稿を出力することにしました。原稿はPDFに変換してもっていけばOKです。
自宅以外のプリンタの印刷で一番気になったのは、拡大縮小せずに印刷するための設定です。原稿は拡大縮小なしで印刷することで上下左右のマージンが均等になるようにレイアウトしているので、プリントするときにPDFを拡大縮小せずに印刷する方法を教えてもらいました、というか1枚縮小されて印刷されてしまったのでそのときに聞きました。
デザイン関係の方には当たり前すぎる話かもしれませんがとりあえず。
ちなみに、キンコーズでプリントアウトするときには設置されているPCをレンタルする形になるのですが、10分単位で課金されるため、そこで時間をくわれたくなかったというのがあります。
拡大縮小せずに印刷する方法
WindowsではPDFを印刷するときに、スクリーンショットの画面が表示されます。
ここでは「ページの拡大/縮小」で「用紙に合わせる」を選択していますが、これでは縮小される場合があるそうです。プリンタのプロパティで原稿と同じサイズの用紙を選択しても同じです。
Adobeの公式サイトの説明では、「用紙に合わせる」を選択したときの動作について、下記のように解説されています。
PDF を拡大縮小して印刷する方法(Acrobat 7.0/Adobe Reader 7.0)
現在選択している用紙サイズに合わせて各ページが拡大縮小されます。領域を選択している場合、または現在選択されている用紙サイズの印刷可能領域に合わせて、領域が拡大縮小されます。
ということで、印刷可能領域の影響で若干縮小されることがあるようです。縮小せずに印刷するには「なし」を選択すればいいそうです。
さきほどのAdobe公式サイトの説明は次の通りです。
拡大縮小せずに印刷されます。[自動回転と中央配置] を選択した場合は中央部に、選択しない場合はページの左上部を基準に印刷されます。用紙に入りきらないページや領域は自動的にトリミングされます。
印刷可能領域からはみ出した部分は印刷されないので、少しマージンをとって原稿を作るといいと思います。
最近のプリンタは「4辺フチなし」とか当たり前にできると思いますが、キンコーズのプリンタはできないそうです。
WordPressのTwenty Elevenテーマ解説:フッター (footer.php)
WordPressの勉強も兼ねて、Twenty Elevenテーマの各テンプレートについて解説しています。確認バージョンは3.2.1です。
フッター (footer.php)
Twenty Elevenテーマの「フッター (footer.php)」は、スクリーンショットの赤枠で示す、WordPressのすべてのページのフッター部分(ヘッダーのdiv要素の終了タグ~</html>まで)に対応しています。
テンプレートのソースコードは次のとおりです。
<?php
/**
* The template for displaying the footer.
*
* Contains the closing of the id=main div and all content after
*
* @package WordPress
* @subpackage Twenty_Eleven
* @since Twenty Eleven 1.0
*/
?>
</div><!-- #main -->
<footer id="colophon" role="contentinfo">
<?php
/* A sidebar in the footer? Yep. You can can customize
* your footer with three columns of widgets.
*/
get_sidebar( 'footer' );
?>
<div id="site-generator">
<?php do_action( 'twentyeleven_credits' ); ?>
<a href="<?php echo esc_url( __( 'http://wordpress.org/', 'twentyeleven' ) ); ?>" title="<?php esc_attr_e( 'Semantic Personal Publishing Platform', 'twentyeleven' ); ?>" rel="generator"><?php printf( __( 'Proudly powered by %s', 'twentyeleven' ), 'WordPress' ); ?></a>
</div>
</footer><!-- #colophon -->
</div><!-- #page -->
<?php wp_footer(); ?>
</body>
</html>
1.フッターメニューの出力
デフォルトの状態では何も表示されていませんが、get_sidebar()でフッターの上部にメニューを追加できます。メニューを追加するには、管理画面の「外観」→「ウィジェット」の赤枠部分に任意のウィジェットをドラッグします。
下のスクリーンショットはフッターメニューを追加したところです。
get_sidebar()の役割は、テーマにある「sidebar.php」を取得することです。ここではパラメータに「footer」が設定されているので、「sidebar-footer.php」を取得します。
get_sidebar( 'footer' );
2.テーマクレジットの表示
フックポイント「twentyeleven_credits」でクレジットを表示することができます。
<?php do_action( 'twentyeleven_credits' ); ?>
デフォルトではこのフックポイントを利用している関数はありませんが、functions.phpに次のような関数を追加すれば「Twenty Eleven」というクレジットを表示します。
function add_twentyeleven_credits() {
echo 'Twenty Eleven';
}
add_action('twentyeleven_credits', 'add_twentyeleven_credits');
3.wp_footer()
wp_footer()は、テーマを作成するときに必ず必要なもので、通常はbody要素の終了タグの直前に記述します。wp_footer()を記述した部分に、プラグインで定義したスクリプトなどが出力されます。
wp_footer()は「wp_footer」フックポイントを実行するためだけの機能をもち、wp-includes/general-template.phpに実装されています。
function wp_footer() {
do_action('wp_footer');
}
プラグインなどでは次のように「wp_footer」フックポイントに登録します。この場合はscript要素を出力します。
<?php
/*
Plugin Name: add_script
Description: add_script
Version: 1.0
*/
function add_script() {
echo '<script type="text/javascript">// ... </script>';
}
add_action('wp_footer', 'add_script');
?>
「wp_footer」フックポイントにはデフォルトで2つの関数が登録されています。ひとつはwp_print_footer_scripts()です。
wp-includes/default-filters.php
add_action( 'wp_footer', 'wp_print_footer_scripts' );
wp_print_footer_scripts()は、スクリプトを出力する関数のようです。wp-includes/script-loader.phpに実装されています。
function wp_print_footer_scripts() {
return print_footer_scripts();
}
管理者でログインしている場合は次の1行が出力されます。これは次項で説明する「管理バー」用のスクリプトです。
<script type='text/javascript' src='http://user-domain/wp/wp-includes/js/admin-bar.js?ver=20110131'></script>
4.管理バーの出力
もうひとつはwp_admin_bar_render()で、これはページ上部に表示される管理バーを出力するためのものです。3項で説明したadmin-bar.jsも関係しています。
wp-includes/admin-bar.php
add_action( 'wp_footer', 'wp_admin_bar_render', 1000 );
管理バー

次のようなマークアップを出力します。
<div id="wpadminbar">
<div class="quicklinks">
<ul>
<li id="wp-admin-bar-my-account-with-avatar" class="menupop"><a href="http://user-domain/wp/wp-admin/profile.php"><span><img alt='' src='http://0.gravatar.com/avatar/ef7e5083fd46c3e1959a22621bc624c1?s=16&d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D16&r=G' class='avatar avatar-16 photo' height='16' width='16' />admin</span></a>
<ul>
<li id="wp-admin-bar-edit-profile" class=""><a href="http://user-domain/wp/wp-admin/profile.php">プロフィールを編集</a></li>
<li id="wp-admin-bar-logout" class=""><a href="http://user-domain/wp/wp-login.php?action=logout&_wpnonce=9dc934d1db">ログアウト</a></li>
</ul>
</li>
<li id="wp-admin-bar-dashboard" class=""><a href="http://user-domain/wp/wp-admin/">ダッシュボード</a></li>
<li id="wp-admin-bar-new-content" class="menupop"><a href="http://user-domain/wp/wp-admin/post-new.php?post_type=post"><span>新規追加</span></a>
<ul>
<li id="wp-admin-bar-new-post" class=""><a href="http://user-domain/wp/wp-admin/post-new.php?post_type=post">投稿</a></li>
<li id="wp-admin-bar-new-page" class=""><a href="http://user-domain/wp/wp-admin/post-new.php?post_type=page">固定ページ</a></li>
<li id="wp-admin-bar-new-media" class=""><a href="http://user-domain/wp/wp-admin/media-new.php">メディア</a></li>
<li id="wp-admin-bar-new-link" class=""><a href="http://user-domain/wp/wp-admin/link-add.php">リンク</a></li>
<li id="wp-admin-bar-new-user" class=""><a href="http://user-domain/wp/wp-admin/user-new.php">ユーザー</a></li>
<li id="wp-admin-bar-new-theme" class=""><a href="http://user-domain/wp/wp-admin/theme-install.php">テーマ</a></li>
<li id="wp-admin-bar-new-plugin" class=""><a href="http://user-domain/wp/wp-admin/plugin-install.php">プラグイン</a></li>
</ul>
</li>
<li id="wp-admin-bar-comments" class=""><a href="http://user-domain/wp/wp-admin/edit-comments.php">コメント </a></li>
<li id="wp-admin-bar-appearance" class="menupop"><a href="http://user-domain/wp/wp-admin/themes.php"><span>外観</span></a>
<ul>
<li id="wp-admin-bar-themes" class=""><a href="http://user-domain/wp/wp-admin/themes.php">テーマ</a></li>
<li id="wp-admin-bar-widgets" class=""><a href="http://user-domain/wp/wp-admin/widgets.php">ウィジェット</a></li>
<li id="wp-admin-bar-menus" class=""><a href="http://user-domain/wp/wp-admin/nav-menus.php">メニュー</a></li>
<li id="wp-admin-bar-background" class=""><a href="http://user-domain/wp/wp-admin/themes.php?page=custom-background">背景</a></li>
<li id="wp-admin-bar-header" class=""><a href="http://user-domain/wp/wp-admin/themes.php?page=custom-header">ヘッダー</a></li>
</ul>
</li>
</ul>
</div>
<div id="adminbarsearch-wrap">
<form action="http://user-domain/wp" method="get" id="adminbarsearch">
<input class="adminbar-input" name="s" id="adminbar-search" type="text" value="" maxlength="150" />
<input type="submit" class="adminbar-button" value="検索"/>
</form>
</div>
</div>
管理バーの表示・非表示はプロフィールのページで制御できます。

WordPress「アイキャッチ画像」の使い方
WordPressでは「アイキャッチ画像」という機能が追加されています(2.9~。当時は「投稿サムネイル/投稿画像」という名称だった模様)。
本エントリーでは「アイキャッチ画像」について紹介したいと思います。認識誤り等ありましたらご指摘ください。
1.アイキャッチ画像とは
「アイキャッチ」は「人目を引く」といった意味があり、WordPressの「アイキャッチ画像」とは、記事単位にアイキャッチ用の画像を設定できる機能を指します。
アイキャッチ画像を記事に設定しておけば、記事にひもづいたサムネイルや、ページのヘッダー画像として利用することができます。
TwentyElevenテーマでは次のようにヘッダー画像(赤枠部分)にアイキャッチ画像を表示できます(仕組みについては後述)。
![]()
アイキャッチ画像を利用するには、利用しているテーマにアイキャッチ画像を利用する設定が必要です。設定の詳細は4項で解説します。
2.記事にアイキャッチ画像を設定する
テーマでアイキャッチ画像が利用できるという前提で、記事にアイキャッチ画像を設定する手順を解説します。デフォルトのTwentyEleven/TwentyTenであれば利用可能です。
記事編集画面の右下にある「アイキャッチ画像を設定」をクリック。

画像アップロード後に表示された画面で「アイキャッチ画像として使用」をクリック。このエリアが表示されない場合は、利用しているテーマにアイキャッチ画像の利用できる設定を行う必要があります。設定の詳細は4項を参照してください。
クリックしたリンクが「保存しています」→「完了」と表示が変わって、次の画面になればOKです。右上の×印をクリックして画面を閉じます。

記事編集画面にアイキャッチ画像が設定されました。ここでは次項の説明の都合上、デフォルトのヘッダー画像より少し大きい、1100x290の画像を設定しました。

3.アイキャッチ画像を表示する
TwentyElevenテーマでは次の条件が揃っていれば、冒頭のスクリーンショットで紹介したように、記事ページのヘッダ画像としてアイキャッチ画像が表示されます。スクリーンショットはTwentyElevenテーマの記事ページです。
アイキャッチ画像を表示するには、アイキャッチ画像用のテンプレートタグを設定します。TwentyElevenテーマの記事ページでは、get_the_post_thumbnail()でアイキャッチ画像を表示しています。定義しているのはヘッダー(header.php)です。
echo get_the_post_thumbnail( $post->ID, 'post-thumbnail' );
また、TwentyElevenテーマ(TwentyTenテーマ)の場合は、次の4つの条件を満たしたときだけget_the_post_thumbnail()を実行するようになっています。カッコ内は条件を判定するときに実行しているテンプレートタグまたは関数です。
- 記事ページである(is_singular())
- 記事にアイキャッチ画像が添付されている(has_post_thumbnail())
- 画像の情報(URL、高さ、幅)を取得できる(wp_get_attachment_image_src()+get_post_thumbnail_id())
- 取得した画像の幅がHEADER_IMAGE_WIDTH(1000px)より大きい
通常ここまで複雑な判定を行う必要はないと思いますが、テクニックとして覚えておくと良いかもしれません。
4.利用テーマでアイキャッチ画像を使えるようにする
アイキャッチ画像を利用できるようにするには、テーマのfunctions.phpに次の設定が必要です。
<?php add_theme_support('post-thumbnails'); ?>
TwentyElevenテーマではアクションフック関数twentyeleven_setup()の中でadd_theme_support()を起動しています。
function twentyeleven_setup() {
…中略…
// This theme uses Featured Images (also known as post thumbnails) for per-post/per-page Custom Header images
add_theme_support( 'post-thumbnails' );
が、functions.phpの末尾にadd_theme_support()を追加するだけでも大丈夫です(実験済み)。
5.テンプレートタグ
アイキャッチ画像で使うテンプレートタグです。
- the_post_thumbnail( $size, $attr ):現在の投稿のアイキャッチ画像を表示(ループで利用可)
- get_the_post_thumbnail( $id, $size, $attr ):現在または指定した投稿のアイキャッチ画像を取得
- has_post_thumbnail( $post_id ):現在または指定した投稿にアイキャッチ画像があるか判定
- get_post_thumbnail_id():現在または指定した投稿のアイキャッチ画像IDを取得
6.アイキャッチ画像をリサイズする
アイキャッチ画像を任意のサイズにリサイズするには、テンプレートタグのパラメータに次のように配列で設定します。公式サイトのドキュメントでは2つの値が幅・高さに対応しているように見えますが、実際には2つめの値が幅・高さに適用されるようです。
the_post_thumbnail( array(100, 100) );
get_the_post_thumbnail()の場合は次のように設定します。
echo get_the_post_thumbnail($post->id, array(100,100));
下のスクリーンショットは、TwentyElevenテーマでさきほどアップロードしたアイキャッチ画像を100x100のサムネイルで表示した例です。
元のアイキャッチ画像のサイズは変わらないので、安心してリサイズしてください。
また、the_post_thumbnail()とget_the_post_thumbnail()には、次のようなパラメータ設定でサムネイルを生成できます。「thumbnail」は150x150にリサイズします。他に「medium」「large」も設定できます。
the_post_thumbnail( 'thumbnail' );
7.アイキャッチ画像のimg要素に任意の属性を設定する
the_post_thumbnail()とget_the_post_thumbnail()で出力されるimg要素には、パラメータに任意の属性を設定できます。
the_post_thumbnail( 'thumbnail', array( 'alt' => 'foo', 'title' => 'bar', 'class' => 'abc' ));
width属性、height属性は自動で設定されます。
8.参考サイト
参考サイトは以下です。ありがとうございました。
WordPressのTwenty Elevenテーマ解説:ヘッダー (header.php):その3
WordPressの勉強も兼ねて、Twenty Elevenテーマの各テンプレートについて解説しています。確認バージョンは3.2.1です。
今回は「WordPressのTwenty Elevenテーマ解説:ヘッダー (header.php):その2」の続きです。
ヘッダー (header.php):その3
Twenty Elevenテーマの「ヘッダー (header.php)」は、スクリーンショットの赤枠で示す、WordPressのすべてのページのヘッダー部分(DOCTYPE~<div id="main">まで)に対応しています。
テンプレートのソースコードは次のとおりです。この回で説明するのは青色で示す部分です。
<?php
/**
* The Header for our theme.
*
* Displays all of the <head> section and everything up till <div id="main">
*
* @package WordPress
* @subpackage Twenty_Eleven
* @since Twenty Eleven 1.0
*/
?><!DOCTYPE html>
<!--[if IE 6]>
<html id="ie6" <?php language_attributes(); ?>>
<![endif]-->
<!--[if IE 7]>
<html id="ie7" <?php language_attributes(); ?>>
<![endif]-->
<!--[if IE 8]>
<html id="ie8" <?php language_attributes(); ?>>
<![endif]-->
<!--[if !(IE 6) | !(IE 7) | !(IE 8) ]><!-->
<html <?php language_attributes(); ?>>
<!--<![endif]-->
<head>
<meta charset="<?php bloginfo( 'charset' ); ?>" />
<meta name="viewport" content="width=device-width" />
<title><?php
/*
* Print the <title> tag based on what is being viewed.
*/
global $page, $paged;
wp_title( '|', true, 'right' );
// Add the blog name.
bloginfo( 'name' );
// Add the blog description for the home/front page.
$site_description = get_bloginfo( 'description', 'display' );
if ( $site_description && ( is_home() || is_front_page() ) )
echo " | $site_description";
// Add a page number if necessary:
if ( $paged >= 2 || $page >= 2 )
echo ' | ' . sprintf( __( 'Page %s', 'twentyeleven' ), max( $paged, $page ) );
?></title>
<link rel="profile" href="http://gmpg.org/xfn/11" />
<link rel="stylesheet" type="text/css" media="all" href="<?php bloginfo( 'stylesheet_url' ); ?>" />
<link rel="pingback" href="<?php bloginfo( 'pingback_url' ); ?>" />
<!--[if lt IE 9]>
<script src="<?php echo get_template_directory_uri(); ?>/js/html5.js" type="text/javascript"></script>
<![endif]-->
<?php
/* We add some JavaScript to pages with the comment form
* to support sites with threaded comments (when in use).
*/
if ( is_singular() && get_option( 'thread_comments' ) )
wp_enqueue_script( 'comment-reply' );
/* Always have wp_head() just before the closing </head>
* tag of your theme, or you will break many plugins, which
* generally use this hook to add elements to <head> such
* as styles, scripts, and meta tags.
*/
wp_head();
?>
</head>
<body <?php body_class(); ?>>
<div id="page" class="hfeed">
<header id="branding" role="banner">
<hgroup>
<h1 id="site-title"><span><a href="<?php echo esc_url( home_url( '/' ) ); ?>" title="<?php echo esc_attr( get_bloginfo( 'name', 'display' ) ); ?>" rel="home"><?php bloginfo( 'name' ); ?></a></span></h1>
<h2 id="site-description"><?php bloginfo( 'description' ); ?></h2>
</hgroup>
<?php
// Check to see if the header image has been removed
$header_image = get_header_image();
if ( ! empty( $header_image ) ) :
?>
<a href="<?php echo esc_url( home_url( '/' ) ); ?>">
<?php
// The header image
// Check if this is a post or page, if it has a thumbnail, and if it's a big one
if ( is_singular() &&
has_post_thumbnail( $post->ID ) &&
( /* $src, $width, $height */ $image = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), array( HEADER_IMAGE_WIDTH, HEADER_IMAGE_WIDTH ) ) ) &&
$image[1] >= HEADER_IMAGE_WIDTH ) :
// Houston, we have a new header image!
echo get_the_post_thumbnail( $post->ID, 'post-thumbnail' );
else : ?>
<img src="<?php header_image(); ?>" width="<?php echo HEADER_IMAGE_WIDTH; ?>" height="<?php echo HEADER_IMAGE_HEIGHT; ?>" alt="" />
<?php endif; // end check for featured image or standard header ?>
</a>
<?php endif; // end check for removed header image ?>
<?php
// Has the text been hidden?
if ( 'blank' == get_header_textcolor() ) :
?>
<div class="only-search<?php if ( ! empty( $header_image ) ) : ?> with-image<?php endif; ?>">
<?php get_search_form(); ?>
</div>
<?php
else :
?>
<?php get_search_form(); ?>
<?php endif; ?>
<nav id="access" role="navigation">
<h3 class="assistive-text"><?php _e( 'Main menu', 'twentyeleven' ); ?></h3>
<?php /* Allow screen readers / text browsers to skip the navigation menu and get right to the good stuff. */ ?>
<div class="skip-link"><a class="assistive-text" href="#content" title="<?php esc_attr_e( 'Skip to primary content', 'twentyeleven' ); ?>"><?php _e( 'Skip to primary content', 'twentyeleven' ); ?></a></div>
<div class="skip-link"><a class="assistive-text" href="#secondary" title="<?php esc_attr_e( 'Skip to secondary content', 'twentyeleven' ); ?>"><?php _e( 'Skip to secondary content', 'twentyeleven' ); ?></a></div>
<?php /* Our navigation menu. If one isn't filled out, wp_nav_menu falls back to wp_page_menu. The menu assiged to the primary position is the one used. If none is assigned, the menu with the lowest ID is used. */ ?>
<?php wp_nav_menu( array( 'theme_location' => 'primary' ) ); ?>
</nav><!-- #access -->
</header><!-- #branding -->
<div id="main">
1.body要素のclass属性値の出力
body_class()でbody要素のclass属性を設定します。
<body <?php body_class(); ?>>
メインページでは次のような出力になります。
<body class="home blog single-author two-column right-sidebar">
記事ページでは次のような出力になります。
<body class="single single-post postid-6 single-format-gallery logged-in admin-bar single-author singular two-column right-sidebar">
body_class()はwp-includes/post-template.phpに実装されています。
wp-includes/post-template.php
function body_class( $class = '' ) {
// Separates classes with a single space, collates classes for body element
echo 'class="' . join( ' ', get_body_class( $class ) ) . '"';
}
中で起動されているget_body_class()も同じファイルに実装されています(長いので掲載は割愛)。
2.ブログタイトルとキャッチフレーズの出力

次の部分でブログタイトルとキャッチフレーズを出力します。
<hgroup>
<h1 id="site-title"><span><a href="<?php echo esc_url( home_url( '/' ) ); ?>" title="<?php echo esc_attr( get_bloginfo( 'name', 'display' ) ); ?>" rel="home"><?php bloginfo( 'name' ); ?></a></span></h1>
<h2 id="site-description"><?php bloginfo( 'description' ); ?></h2>
</hgroup>
esc_url()でラップされているhome_url()は、wp-includes/link-template.phpに実装されています。
wp-includes/link-template.php
function home_url( $path = '', $scheme = null ) {
return get_home_url(null, $path, $scheme);
}
中で起動されているget_home_url()も同じファイルに実装されていて、中ではget_option()またはget_blog_option()の値を利用しています。プロトコル(http/https)は、is_ssl()とis_admin()で決定しています。is_ssl()はセキュアなアクセスである場合に実行し、プロトコル(http/https)を振り分けます。
function get_home_url( $blog_id = null, $path = '', $scheme = null ) {
$orig_scheme = $scheme;
if ( !in_array( $scheme, array( 'http', 'https' ) ) )
$scheme = is_ssl() && !is_admin() ? 'https' : 'http';
if ( empty( $blog_id ) || !is_multisite() )
$url = get_option( 'home' );
else
$url = get_blog_option( $blog_id, 'home' );
if ( 'http' != $scheme )
$url = str_replace( 'http://', "$scheme://", $url );
if ( !empty( $path ) && is_string( $path ) && strpos( $path, '..' ) === false )
$url .= '/' . ltrim( $path, '/' );
return apply_filters( 'home_url', $url, $path, $orig_scheme, $blog_id );
}
esc_url()はURLに含まれる文字列をURIエンコードする役割があり、wp-includes/formatting.phpに実装されています。esc_attr()は属性値として設定する文字列をエスケープする役割があり、同じファイルに実装されています。
get_bloginfo( 'name', 'display' ) )でブログ名をa要素のtitle属性に設定します。 bloginfo( 'name' )はブログ名、bloginfo( 'description' )はキャッチフレーズを出力します。get_bloginfo()とbloginfo()は既出のため、解説は省略します。
3.ヘッダ画像の出力
以下の部分でヘッダ画像を出力します。記事ページではアイキャッチ画像を表示することもできます。アイキャッチ画像の詳細については別途エントリーしたいと思います。
<?php
// Check to see if the header image has been removed
$header_image = get_header_image();
if ( ! empty( $header_image ) ) :
?>
<a href="<?php echo esc_url( home_url( '/' ) ); ?>">
<?php
// The header image
// Check if this is a post or page, if it has a thumbnail, and if it's a big one
if ( is_singular() &&
has_post_thumbnail( $post->ID ) &&
( /* $src, $width, $height */ $image = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), array( HEADER_IMAGE_WIDTH, HEADER_IMAGE_WIDTH ) ) ) &&
$image[1] >= HEADER_IMAGE_WIDTH ) :
// Houston, we have a new header image!
echo get_the_post_thumbnail( $post->ID, 'post-thumbnail' );
else : ?>
<img src="<?php header_image(); ?>" width="<?php echo HEADER_IMAGE_WIDTH; ?>" height="<?php echo HEADER_IMAGE_HEIGHT; ?>" alt="" />
<?php endif; // end check for featured image or standard header ?>
</a>
<?php endif; // end check for removed header image ?>
get_header_image()は画像のURLを収集する役割があり、変数$header_imageに次のようなURLを設定します。
http://user-domain/wp/wp-content/themes/twentyeleven/images/headers/trolley.jpg
get_header_image()はwp-includes/theme.phpに実装されています。
wp-includes/theme.php
function get_header_image() {
$default = defined( 'HEADER_IMAGE' ) ? HEADER_IMAGE : '';
$url = get_theme_mod( 'header_image', $default );
if ( 'remove-header' == $url )
return false;
if ( is_random_header_image() )
$url = get_random_header_image();
if ( is_ssl() )
$url = str_replace( 'http://', 'https://', $url );
else
$url = str_replace( 'https://', 'http://', $url );
return esc_url_raw( $url );
}
HEADER_IMAGEはテーマのfunctions.phpのtwentyeleven_setup()に定義されています(ただし値は空)。
function twentyeleven_setup() {
//...
define( 'HEADER_IMAGE', '' );
get_theme_mod()はテーマのオプションを取得する関数で、後述します。
remove-headerの判定は、「外観」→「ヘッダー」で「ヘッダー画像を削除」をクリックした場合に実行されるものと思われます(間違っていたらすいません)。

is_random_header_image()は同じ管理画面で「ランダム」を選択している場合に実行される関数で、wp-includes/theme.phpに実装されています。

return時のesc_url_raw()は、esc_url()をラップした関数で、wp-includes/formatting.phpに実装されています。
function esc_url_raw( $url, $protocols = null ) {
return esc_url( $url, $protocols, 'db' );
}
話を戻して、変数$header_imageに値が設定されていれば(=ヘッダ画像のURLがあれば)、home_url()とesc_url()を組み合わせて、ブログのメインページのリンクを出力します。
if ( ! empty( $header_image ) ) :
?>
<a href="<?php echo esc_url( home_url( '/' ) ); ?>">
// ...
</a>
<?php endif; // end check for removed header image ?>
リンクのコンテンツの出力部分は以下です。
<?php
// The header image
// Check if this is a post or page, if it has a thumbnail, and if it's a big one
if ( is_singular() &&
has_post_thumbnail( $post->ID ) &&
( /* $src, $width, $height */ $image = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), array( HEADER_IMAGE_WIDTH, HEADER_IMAGE_WIDTH ) ) ) &&
$image[1] >= HEADER_IMAGE_WIDTH ) :
// Houston, we have a new header image!
echo get_the_post_thumbnail( $post->ID, 'post-thumbnail' );
else : ?>
<img src="<?php header_image(); ?>" width="<?php echo HEADER_IMAGE_WIDTH; ?>" height="<?php echo HEADER_IMAGE_HEIGHT; ?>" alt="" />
<?php endif; // end check for featured image or standard header ?>
次の4つの条件を満たす場合、get_the_post_thumbnail()でアイキャッチ画像を出力します。
- 記事ページである(is_singular())
- 記事に画像が添付されている(post-thumbnail-template.php/has_post_thumbnail())
- 画像の情報(URL、高さ、幅)を取得できる
- 取得した画像の幅がHEADER_IMAGE_WIDTH(1000px)より大きい
get_the_post_thumbnail( $post->ID, 'post-thumbnail' );
上記以外の場合は、Twenty Elevenテーマで用意されている画像を表示します。
<img src="<?php header_image(); ?>" width="<?php echo HEADER_IMAGE_WIDTH; ?>" height="<?php echo HEADER_IMAGE_HEIGHT; ?>" alt="" />
header_image()はget_header_image()をechoする関数で、wp-includes/theme.phpに実装されています。
4.検索フォームの出力

次の部分で検索フォームを出力します。
<?php
// Has the text been hidden?
if ( 'blank' == get_header_textcolor() ) :
?>
<div class="only-search<?php if ( ! empty( $header_image ) ) : ?> with-image<?php endif; ?>">
<?php get_search_form(); ?>
</div>
<?php
else :
?>
<?php get_search_form(); ?>
<?php endif; ?>
デフォルトの状態ではページの右上に検索フォームを表示しますが、get_header_textcolor()の結果が「blank」であればdiv要素を挿入して、検索フォームをナビゲーションの右側に出力するようになっています。
get_header_textcolor()はHEADER_TEXTCOLORの値を出力する関数で、wp-includes/theme.phpに実装されています。
wp-includes/theme.php
function get_header_textcolor() {
$default = defined('HEADER_TEXTCOLOR') ? HEADER_TEXTCOLOR : '';
return get_theme_mod('header_textcolor', $default);
}
HEADER_TEXTCOLORは、テーマのfunctions.phpのtwentyeleven_setup()に定義されています。
function twentyeleven_setup() {
//...
define( 'HEADER_TEXTCOLOR', '000' );
twentyeleven_setup()は、functions.phpにある「after_setup_them」フックポイントで起動されます。
add_action( 'after_setup_theme', 'twentyeleven_setup' );
get_theme_mod()は、現在のテーマについて第1パラメータで指定したキーの値(modification value)を取得する関数のようです。キーと値はテーマを切り替えたときにwp_optionsテーブルに保存されるようです。
function get_theme_mod( $name, $default = false ) {
$mods = get_theme_mods();
if ( isset( $mods[ $name ] ) )
return apply_filters( "theme_mod_$name", $mods[ $name ] );
return apply_filters( "theme_mod_$name", sprintf( $default, get_template_directory_uri(), get_stylesheet_directory_uri() ) );
}
get_theme_mods()も同じファイルに実装されています。
function get_theme_mods() {
$theme_slug = get_option( 'stylesheet' );
if ( false === ( $mods = get_option( "theme_mods_$theme_slug" ) ) ) {
$theme_name = get_current_theme();
$mods = get_option( "mods_$theme_name" ); // Deprecated location.
if ( is_admin() && false !== $mods ) {
update_option( "theme_mods_$theme_slug", $mods );
delete_option( "mods_$theme_name" );
}
}
return $mods;
}
get_theme_mods()は取得関数ですが、オプションの設定はadd_option()、更新はupdate_option()、またオプションの削除関数としてremove_theme_mods()があります。add_option()とupdate_option()はwp-includes/functions.phpに実装されています。
テーマの切り替えなどを行うと、これらの関数が実行されるようです。
5.ナビゲーションの出力

最後に、次の部分でナビゲーションを出力します。
<nav id="access" role="navigation">
<h3 class="assistive-text"><?php _e( 'Main menu', 'twentyeleven' ); ?></h3>
<?php /* Allow screen readers / text browsers to skip the navigation menu and get right to the good stuff. */ ?>
<div class="skip-link"><a class="assistive-text" href="#content" title="<?php esc_attr_e( 'Skip to primary content', 'twentyeleven' ); ?>"><?php _e( 'Skip to primary content', 'twentyeleven' ); ?></a></div>
<div class="skip-link"><a class="assistive-text" href="#secondary" title="<?php esc_attr_e( 'Skip to secondary content', 'twentyeleven' ); ?>"><?php _e( 'Skip to secondary content', 'twentyeleven' ); ?></a></div>
<?php /* Our navigation menu. If one isn't filled out, wp_nav_menu falls back to wp_page_menu. The menu assiged to the primary position is the one used. If none is assigned, the menu with the lowest ID is used. */ ?>
<?php wp_nav_menu( array( 'theme_location' => 'primary' ) ); ?>
</nav><!-- #access -->
以下は出力例です。
<nav id="access" role="navigation">
<h3 class="assistive-text">メインメニュー</h3>
<div class="skip-link"><a class="assistive-text" href="#content" title="メインコンテンツへ移動">メインコンテンツへ移動</a></div>
<div class="skip-link"><a class="assistive-text" href="#secondary" title="サブコンテンツへ移動">サブコンテンツへ移動</a></div>
<div class="menu"><ul><li class="current_page_item"><a href="http://localhost/wordpress321/" title="ホーム">ホーム</a></li><li class="page_item page-item-2"><a href="http://localhost/wordpress321/?page_id=2" title="サンプルページ">サンプルページ</a></li></ul></div>
</nav><!-- #access -->
wp_nav_menu()はナビゲーションメニューを出力するための関数で、wp-includes/nav-menu-template.phpに実装されています(掲載は割愛)。wp_nav_menu()には色々なオプションがありますが、詳細は別途エントリーしたいと思います。
Twenty Elevenテーマでは、テーマ内で使用する場所(ロケーション)を示す「theme_location」のみを設定しています。「theme_location」の値「primary」は、functions.phpにregister_nav_menu()で設定しています。
// This theme uses wp_nav_menu() in one location.
register_nav_menu( 'primary', __( 'Primary Menu', 'twentyeleven' ) );
functions.phpにregister_nav_menu()を追加していけば、ロケーションのバリエーションを増やすことができます。
register_nav_menu( 'secondary', 'フッターメニュー' );
register_nav_menu()で複数のロケーションをまとめて設定することもできます。
register_nav_menus( array(
'primary' => __( 'Primary Navigation', 'twentyten' ),
'secondary' => 'フッターメニュー',
'thirdly' => 'サイドメニュー',
) );
肝心のメニューの内容は、管理画面の「外観」→「メニュー」で設定します。
デフォルト状態では何も設定されていないので、先程の「フッターメニュー」用のメニュー内容を作りたい場合は、「メニューの名前」に「フッター」など任意の名称を入力して「メニューを作成」をクリック。

作成すると左側にメニュー項目として「カスタムリンク」「固定ページ」「カテゴリー」などがアクティブになり、同時に「register_nav_menus」に対応する「テーマの場所(ロケーション)」も表示されます。

あとはそれぞれのロケーションに作成したメニューを作って「保存」をクリックします。フッターメニューは、テーマの「フッター」に次の記述すれば表示されます。
<?php wp_nav_menu( array( 'theme_location' => 'secondary' ) ); ?>
Movable Typeで携帯サイト向けに画像を縮小表示する「ImageSizeModifierプラグイン」
Category:[自作プラグイン]
Tag:[ImageSizeModifier, MovableType, Plugin]
Permalink
Movable Typeで携帯サイト向けに画像を縮小する「ImageSizeModifierプラグイン」を公開します。
1.目的
スマホサイト向けのページは「jQueryでスマホサイト向けに画像サイズを縮小する方法」で紹介した通り、jQueryで画像サイズの変更が可能ですが、携帯サイトではJavaScriptが使えないキャリアがあるため、再構築によるページ出力時にimg要素のwidth属性を書き換えて、画像を縮小表示します。
変更可能なimg要素の属性は、次のルールで並んでいる必要があります。
- src属性の後方にwidth属性・height属性あること
- width属性・height属性の順序は不定。ただし属性間に別の属性が含まれないこと
- alt属性はimg要素の直後かsrc属性の直後のみ許容
- width属性またはheight属性の前のclass属性・style属性は許容。ただしclass属性・style属性の順に並んでいること
- width属性・height属性の後方の属性は何でも許容
下は上記ルールを許容する例です。
<img src="..." width="..." height="..."
<img alt="..." src="..." width="..." height="..."
<img src="..." alt="..." height="..." width="..."
<img alt="..." src="..." class="..." style="..." height="..." width="..."
<img alt="..." src="..." width="..." height="..." class="..." style="..."
MTのデフォルト機能を使って記事に挿入した画像のimg要素が縮小されることは、バージョン5.12で確認しています。
すいませんが携帯サイトでの表示は未確認です。
2.機能
- ブログ記事に記述されているimg要素のwidth属性値・height属性値について、ページ再構築時にプラグインで指定したサイズに変換します。
- 画像サイズを変更するテンプレートをプラグインで指定できます。
3.価格
- 個人無償版/有償版での非商用利用/Movable Type Open Source:無償
- 有償版での商用利用:1050円/1サーバ(事前に動作確認してください)
無償でご利用の場合も、プラグインのご利用についてご支援・ご賛同くださる方からの寄付をお待ち申し上げます。
4.プラグインのダウンロード
下記のリンクからプラグインアーカイブをダウンロードし、任意のフォルダに保存してください。
修正履歴
2011.09.20 初版
- ImageSizeModifier_0_01.zip(MT4.x/MT5.0x/MT5.1x対応)
5.プラグインのインストール
プラグインアーカイブを解凍し、pluginsフォルダ配下にあるImageSizeModifierフォルダをpluginsディレクトリにアップロードしてください。
管理画面の「システム」→「プラグイン」でプラグイン設定画面を表示し、「ImageSizeModifier」が表示されればOKです。

6.プラグインの設定
プラグインを利用したいウェブサイトまたはブログ管理画面の「ツール」→「プラグイン」→「ImageSizeModifier」→「設定」でプラグイン設定画面を表示し、次の項目を設定します。
- テンプレートID:画像の幅を変更するテンプレートID。複数ある場合はカンマで区切る(カンマ前後の半角スペースは許容)
- 画像の幅:img要素のwidth属性に設定したい値。height属性値は比率を保った値を自動設定します

7.注意事項
このプラグインは、出力するページに含まれるすべてのimg要素に対して適用します。適用対象にしたくないimg要素は、1項に掲載している属性の並び順を変更してください。
また、変換後にはimg要素のsrc属性・width属性・height属性以外の属性は削除されます。
Facebookフィード購読機能の徹底解説
Facebookでフィード購読機能が公開されました。すでにあちこちで紹介されていますが、フィード購読機能を使って友達以外のユーザーの投稿を読む方法や、自分の投稿をフィードを使って公開する方法などを詳しく紹介します。
1.登場人物
動作確認はいつもの通り、テストユーザーを使っています。
説明で登場する人物は以下です。
- Daveさん:フィードを公開する人
- Helenさん:フィードを購読する人
- Elizabethさん:HelenさんとDaveさんのFacebook上の友達
テストユーザー同士は、赤の他人ではフィードが購読できないようなので(間違ってたらすいません)、Elizabethさんを介してHelenさんがDaveさんの公開するフィードを購読するという図式にしています。

Elizabethさんは単なるつなぎなので、以降の説明には登場しません。
2.友達以外のユーザーに自分の記事をフィードで公開する
まずDaveさんが自分の記事をフィードで公開する手順を解説します。
DaveさんがFacebookにログインして「プロフィール」をクリック。

左メニューの「フィード購読」をクリック。

「フィード購読を許可します」をクリック。このリンクが表示されていない場合は、「フィード購読」ページの右にある緑色の「フィード購読を許可します」をクリック。

購読者設定の編集ダイアログが開きます。
上のプルダウンメニューでコメント許可のオン・オフを設定します。

下のプルダウンメニューで新しい購読者があったときのお知らせを受ける対象を設定します。

これで設定完了です。Daveさんのプロフィールページの左メニューに「フィード購読者」というメニューが追加されます。

「フィード購読者」をクリックすると、Daveさんのフィード購読者はまだ一人もいないので、次のように表示されます。
3.友達以外のユーザーの投稿をフィードで読む
次にHelenさん主役で、Elizabethさんの友達(つまり友達の友達)であるDaveさんのフィードを購読する手順を解説します。
Facebookにログインして「プロフィール」をクリック。

フィードを読みたい人(Daveさん)のページに進んで、右上にある「フィード購読する」をクリック。
クリックすると、Daveさんのページの「フィード購読する」の表示が「フィード購読済み」に切り替わります。これでDaveさんのフィード購読の設定ができました。

Helenさんのプロフィールページ左メニューの「フィード購読」にDaceさんの購読分の「1」が加算されます。

「フィード購読(1)」のリンクをクリックすれば、Helenさんが購読しているユーザーの一覧(ここではDaveさんのみ)が表示されます。
Daveさんのプロフィールページには「フィード購読者」の右にHelenさん分の「1」が表示され、「フィード購読者(1)」をクリックすれば、Daveさんのフィードを購読しているユーザーの一覧(ここではHelenさんのみ)が表示されます。
肝心のDaveさんのフィードはどこに表示されるかというと、友達の投稿と同じように、Helenさんのニュースフィードに表示されます。「外部のフィードリーダーで読める」という訳ではないようです。
Daveさんが友達向けに投稿した記事は、Helenさんのニュースフィードには表示されません。

4.フィードの購読をやめる
HelenさんがDaveさんのフィードの購読をやめる場合は、フィード購読中のユーザー一覧の右側にある「フィード購読済み」のボタンをクリックし、メニューから「フィード購読をやめる」を選択します。
あるいはDaveさんのページに進み、「フィード購読済み」ボタンをクリックしても同じメニューが表示されます。
5.フィードの公開をやめる
Daveさんがフィードの公開をやめるには、「フィード購読者」のページの右上にある「設定を編集」をクリック。
購読者設定の編集ダイアログが開くので、一番上の「購読者数」を「オフ」にします。
6.フィードの購読範囲などを決める
HelenさんがDaveさんのフィードの購読範囲などを決めるには、フィード購読中のユーザー一覧の右側にある「フィード購読済み」のボタンをクリックし、メニューからカスタマイズします。
7.フィード機能についてもっと知りたい場合
Facebookヘルプセンターの「よく使うページ » 購読」のページに解説があります。
8.友達のフィードは?
友達のフィードは「フィード購読済み」の状態になっています。つまり友達になった瞬間にフィード購読するという扱いになるようです。ただしフィード購読者にはカウントされません。
「Facebookページプロフェッショナルガイド」4刷決定
先月の15日頃、共著「Facebookページプロフェッショナルガイド」の3刷が決まり増刷されましたが、1ヶ月で4刷が決定致しました。
お買い上げくださった皆様、本当にありがとうございます。
毎日コミュニケーションズ
売り上げランキング: 699
私がこれまでに執筆に関わらせて頂いた書籍では3刷までが最高だったので、4刷は初めてです。ちょっと感激です。
なお、書籍が発売されてからFacebookの仕様変更がちょくちょくあり、内容の乖離が発生しているので、そちらについてはFacebookページ「FBページプロフェッショナルガイド」でサポートさせて頂いてます。書籍を購入された方や内容に不明な点がある方は「FBページプロフェッショナルガイド」へお越しください。
抱き合わせの告知ですいませんが、以前開催した「書籍「Facebookページプロフェッショナルガイド」プレゼント企画」は、当選者の方2名に送付させて頂きました。当選された方おめでとうございます。また、惜しくもはずれてしまった皆様すいません。
「8.8.8.8,8.8.4.4」より速い「129.250.35.250」
iPhoneのDNSの設定変更が話題になっているようなので、レスポンスの速いDNSサーバがないか調べてみました。便乗記事です。
測定ツールはWindows用の「DNS Nameserver Performance Benchmark」です。ツールの詳細は割愛しますが、測定するには下のスクリーンショットの「Nameservers」タグの右側にある「Run Benchmark」をクリックするだけです。
Bフレッツ接続のPCで測定しています。
1.ベンチマーク結果
まずはベンチマーク結果をご覧ください(クリックすればちょっと拡大します)。
測定している値は次の3種類です。それぞのれの意味については「私家版 ITプロフェッショナルの仕事術 - GRCのDNS BenchmarkでDNSをスピードアップ」の記事が分かりやすいと思います。
- Cached lookups(赤)
- Uncached lookups(緑)
- Dotcom lookups(青)
表は、上位4つのDNSサーバのそれぞれの値です(測定ツールの画面をクリックすると値が表示されます)。単位はsecだと思いますが間違ってたらご指摘ください。
| DNS | Cache | Uncached | Dotcom |
|---|---|---|---|
| 129.250.35.250 | 0.009 | 0.111 | 0.067 |
| 8.8.4.4 | 0.009 | 0.167 | 0.147 |
| 8.8.8.8 | 0.009 | 0.179 | 0.131 |
| 129.250.35.251 | 0.018 | 0.119 | 0.093 |
いずれも棒が短い方が速いです。
で、話題になっているGoogle Public DNSの「8.8.8.8」「8.8.4.4」も早いですが、NTT America Technical Operationsの「129.250.35.250」がトップで、「129.250.35.251」もひけをとらない速さです。何回か測定してみましたが順位は同じでした。
測定対象のDNSサーバは、測定ツールにデフォルトで設定されているものなので、調べればもっと速いDNSサーバがあるかもしれません(測定ツールに追加できます)。
PCに設定してみましたが、デフォルトのDNSサーバと比較して体感するほどの大差はありませんでした。そういう人は現状のままでいいんじゃないかと思いますが、iPhoneなどに設定すると変わるのかもしれません。
調べてみたかっただけなので「DNS設定を変更しましょう」というつもりはありませんが、この記事を見て設定する人もいるかもしれませんので、反対派の方に先に謝っておきます。こんな記事書いてすいません。
2.Windows(7/Vista)にDNSを設定する手順
「スタート」→「コントロールパネル」→「ネットワークの状態とタスクの表示」をクリック。

ローカルエリア接続の右側にある「状態の表示」をクリック。

「プロパティ」をクリック。

「インターネットプロトコルバージョン4(TCP/IPv4)」を選択して「プロパティ」をクリック。

「次のDNSサーバーのアドレスを使う」を選択して、「優先DNSサーバー」「代替DNSサーバー」の右側にIPアドレスを設定して「OK」をクリック。
![]()
元の画面も「OK」または「閉じる」ですべて閉じれば完了です。
3.参考サイト
参考サイトは以下です。ありがとうございました。
jQueryでスマホサイト向けに画像サイズを縮小する方法
jQueryでスマホサイト向けに画像サイズを縮小する方法を紹介します。
1.サンプル
次のようなPCサイト用のページがあります。この場合、Movable Typeでページを出力しています。ページで使っている記事内の画像サイズは幅470pxです。
このページをスマホサイト向けに別のページを作り、画像サイズを縮小して表示します。画像サイズは幅280pxに縮小しています。
![]()
2.カスタマイズ
サイズを変更するには、下記のスクリプトをページ内にあるhead終了タグの直前に追加します。
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.3/jquery.min.js"></script>
<script type="text/javascript">
jQuery(function(){
$('img').each(function(){
var max = 280; // 最大幅
var w = $(this).width();
var h = $(this).height();
if (w > max) {
$(this).width(max).height(Math.round((max/w)*h));
}
});
});
</script>
最大幅を示す変数max(ここでは赤色で示す280px)を超える画像について、最大幅に縮小します。maxの値は適宜変更してください。
3.ページをPCサイトと共用したい/ユーザーエージェント別に振り分けたい場合
ページをPCサイトと共用したい場合や、ユーザーエージェント別に振り分けて画像サイズを変更したい場合は、次のようにnavigator.userAgentの判定文を追加し、それぞれに最大値を設定します。
<script type="text/javascript">
jQuery(function(){
$('img').each(function(){
var max = 0;
if (navigator.userAgent.indexOf('iPhone') > 0) {
max = 280; // iPhoneの最大幅
} else if (navigator.userAgent.indexOf('iPad') > 0 ) {
max = 768; // iPadの最大幅
} else if (navigator.userAgent.indexOf('iPod') > 0 ) {
max = 280; // iPodの最大幅
} else if (navigator.userAgent.indexOf('Android') > 0) {
max = 280; // Androidの最大幅
}
var w = $(this).width();
var h = $(this).height();
if (max != 0 && w > max) {
$(this).width(max).height(Math.round((max/w)*h));
}
});
});
</script>
2項と同様、maxの値は適宜修正してください。PCサイトでは画像サイズの縮小を行わないように制御しています。
Movable TypeのTwitter公式アカウントのフォロワー数が少ない件について
Movable TypeのTwitter公式アカウント@movabletypeについてのお知らせです。
Movable TypeのTwitter公式アカウント@movabletypeは、2009年に米国シックスアパートで取得されましたが、現在は日本シックスアパートがMovable Typeのアカウントを引き継いで運営しています。
で、現在のフォロワー数は130(2011年9月14日現在)と、かなり少ないです。
理由は、アカウントを引き継いだ際、Twitterの規約上、フォロワー数が「0」にリセットされてしまったためらしいです。フォローが切れてしまっていることに気がついていないMTユーザーも少なくないのではないでしょうか。
ということで、フォローが切れたMTユーザーの皆様、Movable TypeのTwitter公式アカウント@movabletypeを再度フォローしましょう。フォローしていなかった方もこの機会にフォローしてみてはいかがでしょうか。
ちなみに日英両言語で運営しています。
WordPressのTwenty Elevenテーマ解説:ヘッダー (header.php):その2
WordPressの勉強も兼ねて、Twenty Elevenテーマの各テンプレートについて解説しています。確認バージョンは3.2.1です。
今回は「WordPressのTwenty Elevenテーマ解説:ヘッダー (header.php):その1」の続きです。
ヘッダー (header.php):その2
Twenty Elevenテーマの「ヘッダー (header.php)」は、スクリーンショットの赤枠で示す、WordPressのすべてのページのヘッダー部分(DOCTYPE~<div id="main">まで)に対応しています。
テンプレートのソースコードは次のとおりです。この回で説明するのは青色で示す部分です。
<?php
/**
* The Header for our theme.
*
* Displays all of the <head> section and everything up till <div id="main">
*
* @package WordPress
* @subpackage Twenty_Eleven
* @since Twenty Eleven 1.0
*/
?><!DOCTYPE html>
<!--[if IE 6]>
<html id="ie6" <?php language_attributes(); ?>>
<![endif]-->
<!--[if IE 7]>
<html id="ie7" <?php language_attributes(); ?>>
<![endif]-->
<!--[if IE 8]>
<html id="ie8" <?php language_attributes(); ?>>
<![endif]-->
<!--[if !(IE 6) | !(IE 7) | !(IE 8) ]><!-->
<html <?php language_attributes(); ?>>
<!--<![endif]-->
<head>
<meta charset="<?php bloginfo( 'charset' ); ?>" />
<meta name="viewport" content="width=device-width" />
<title><?php
/*
* Print the <title> tag based on what is being viewed.
*/
global $page, $paged;
wp_title( '|', true, 'right' );
// Add the blog name.
bloginfo( 'name' );
// Add the blog description for the home/front page.
$site_description = get_bloginfo( 'description', 'display' );
if ( $site_description && ( is_home() || is_front_page() ) )
echo " | $site_description";
// Add a page number if necessary:
if ( $paged >= 2 || $page >= 2 )
echo ' | ' . sprintf( __( 'Page %s', 'twentyeleven' ), max( $paged, $page ) );
?></title>
<link rel="profile" href="http://gmpg.org/xfn/11" />
<link rel="stylesheet" type="text/css" media="all" href="<?php bloginfo( 'stylesheet_url' ); ?>" />
<link rel="pingback" href="<?php bloginfo( 'pingback_url' ); ?>" />
<!--[if lt IE 9]>
<script src="<?php echo get_template_directory_uri(); ?>/js/html5.js" type="text/javascript"></script>
<![endif]-->
<?php
/* We add some JavaScript to pages with the comment form
* to support sites with threaded comments (when in use).
*/
if ( is_singular() && get_option( 'thread_comments' ) )
wp_enqueue_script( 'comment-reply' );
/* Always have wp_head() just before the closing </head>
* tag of your theme, or you will break many plugins, which
* generally use this hook to add elements to <head> such
* as styles, scripts, and meta tags.
*/
wp_head();
?>
</head>
<body <?php body_class(); ?>>
<div id="page" class="hfeed">
<header id="branding" role="banner">
<hgroup>
<h1 id="site-title"><span><a href="<?php echo esc_url( home_url( '/' ) ); ?>" title="<?php echo esc_attr( get_bloginfo( 'name', 'display' ) ); ?>" rel="home"><?php bloginfo( 'name' ); ?></a></span></h1>
<h2 id="site-description"><?php bloginfo( 'description' ); ?></h2>
</hgroup>
<?php
// Check to see if the header image has been removed
$header_image = get_header_image();
if ( ! empty( $header_image ) ) :
?>
<a href="<?php echo esc_url( home_url( '/' ) ); ?>">
<?php
// The header image
// Check if this is a post or page, if it has a thumbnail, and if it's a big one
if ( is_singular() &&
has_post_thumbnail( $post->ID ) &&
( /* $src, $width, $height */ $image = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), array( HEADER_IMAGE_WIDTH, HEADER_IMAGE_WIDTH ) ) ) &&
$image[1] >= HEADER_IMAGE_WIDTH ) :
// Houston, we have a new header image!
echo get_the_post_thumbnail( $post->ID, 'post-thumbnail' );
else : ?>
<img src="<?php header_image(); ?>" width="<?php echo HEADER_IMAGE_WIDTH; ?>" height="<?php echo HEADER_IMAGE_HEIGHT; ?>" alt="" />
<?php endif; // end check for featured image or standard header ?>
</a>
<?php endif; // end check for removed header image ?>
<?php
// Has the text been hidden?
if ( 'blank' == get_header_textcolor() ) :
?>
<div class="only-search<?php if ( ! empty( $header_image ) ) : ?> with-image<?php endif; ?>">
<?php get_search_form(); ?>
</div>
<?php
else :
?>
<?php get_search_form(); ?>
<?php endif; ?>
<nav id="access" role="navigation">
<h3 class="assistive-text"><?php _e( 'Main menu', 'twentyeleven' ); ?></h3>
<?php /* Allow screen readers / text browsers to skip the navigation menu and get right to the good stuff. */ ?>
<div class="skip-link"><a class="assistive-text" href="#content" title="<?php esc_attr_e( 'Skip to primary content', 'twentyeleven' ); ?>"><?php _e( 'Skip to primary content', 'twentyeleven' ); ?></a></div>
<div class="skip-link"><a class="assistive-text" href="#secondary" title="<?php esc_attr_e( 'Skip to secondary content', 'twentyeleven' ); ?>"><?php _e( 'Skip to secondary content', 'twentyeleven' ); ?></a></div>
<?php /* Our navigation menu. If one isn't filled out, wp_nav_menu falls back to wp_page_menu. The menu assiged to the primary position is the one used. If none is assigned, the menu with the lowest ID is used. */ ?>
<?php wp_nav_menu( array( 'theme_location' => 'primary' ) ); ?>
</nav><!-- #access -->
</header><!-- #branding -->
<div id="main">
1.link要素の出力
スタイルシートとピンバックのlink要素を出力します。link要素のhref属性の出力にはbloginfo()を利用しています。
<link rel="profile" href="http://gmpg.org/xfn/11" />
<link rel="stylesheet" type="text/css" media="all" href="<?php bloginfo( 'stylesheet_url' ); ?>" />
<link rel="pingback" href="<?php bloginfo( 'pingback_url' ); ?>" />
その1でも解説していますが、bloginfo()はwp-includes/general-template.phpに実装されていて、get_bloginfo()をキックしています。get_bloginfo()については「その1」の4項を参照してください。
wp-includes/general-template.php
function bloginfo( $show='' ) {
echo get_bloginfo( $show, 'display' );
}
2.script要素の出力
ブラウザがIEでバージョンがIE9以下の場合、script要素にget_template_directory_uri()を組み合わせて、html5.jsを読み込みます。
<!--[if lt IE 9]>
<script src="<?php echo get_template_directory_uri(); ?>/js/html5.js" type="text/javascript"></script>
<![endif]-->
script要素のsrc属性は、
http://user-domain/wp-content/themes/twentyeleven/js/html5.js
という風に、Twenty Elevenテーマに含まれているhtml5.jsのURLを出力します。
get_template_directory_uri()はテーマディレクトリのURLを出力する関数で、wp-includes/theme.phpに実装されています。
wp-includes/theme.php
function get_template_directory_uri() {
$template = get_template();
$theme_root_uri = get_theme_root_uri( $template );
$template_dir_uri = "$theme_root_uri/$template";
return apply_filters( 'template_directory_uri', $template_dir_uri, $template, $theme_root_uri );
}
get_template()もwp-includes/theme.phpに実装されています。
function get_template() {
return apply_filters('template', get_option('template'));
}
get_template()は何をやっているのか分かりにくいのですが、まずget_option()の結果を取得し、その後apply_filters()を実行しています。つまり、フックポイント「template」を使ってget_option()で取得した内容をフィルタできるということです。
例えば次のプラグインを適用すれば、get_template()の出力結果の末尾に「hoge」という文字列を追加できます。
<?php
/*
Plugin Name: hoge
Description: hoge
Version: 1.0
*/
function hoge($template) {
return $template . "hoge";
}
add_filter('template', 'hoge', $template);
?>
get_option()はwp-includes/functions.phpに実装されており(コード掲載は割愛)、get_option('template')は「twentyeleven」という文字列を返却します。
get_option()を利用すればさまざまなオプションデータを取得できるようです。get_option()のパラメータに設定可能な値はOption Referenceを参照してください。
get_option()の中でwp_load_alloptions()という関数を実行しているので、以下の1行を実行すればどのようなオプションがあるか分かるかもしれません。get_bloginfo()の一部のデータもget_option()を利用しているようです。
var_dump(wp_load_alloptions());
話を戻して、get_theme_root_uri()はWordPressのthemesディレクトリに対応するURLを取得する関数で、wp-includes/theme.phpに実装されています(掲載は割愛)。
$theme_root_uri = get_theme_root_uri( $template );
なお、get_theme_root_uri()の中でさらにcontent_url()という関数を起動しています。content_url()はプロトコル(http/https)を決める役割と、パラメータに指定した文字列をURLの末尾に追加する役割があるようです。wp-includes/link-template.phpに実装されています。
3.コメント返信用JavaScriptライブラリの出力
シングルページかつスレッドコメントに対応している場合、コメント返信用JavaScriptライブラリのscript要素を出力します。
if ( is_singular() && get_option( 'thread_comments' ) )
wp_enqueue_script( 'comment-reply' );
出力結果は次のようになります。
<script type='text/javascript' src='http://use-domain/wordpress/wp-includes/js/comment-reply.js?ver=20090102'></script>
is_singular()は、シングルページ (固定ページ、個別投稿ページ、添付ファイルページ)であることを判定する関数で、wp-includes/query.phpに実装されています(掲載は割愛)。is_single()、is_page() 、is_attachment() のいずれかがtrueである場合にtrueを返却します。
wp_enqueue_script()でscript要素を出力します。この関数については次項で解説します。
4.wp_enqueue_script()について
wp_enqueue_script()は、同一のJavaScriptライブラリを重複して出力させない役割があります。
今回の例で言うと、プラグイン内で
wp_enqueue_script('comment-reply');
を使ってコメントスレッド用のライブラリを出力する指定を行っておけば、コメントスレッド用ライブラリのscript要素は、Twenty Elevenテーマのヘッダーに記述されている、
wp_enqueue_script( 'comment-reply' );
とあわせて1回しか出力しません。
よくあるケースとして、プラグインでjqueryライブラリを使用する場合、プラグインに次のように記述します。
<?php
function my_scripts_method() {
wp_enqueue_script( 'jquery' );
}
add_action('wp_enqueue_scripts', 'my_scripts_method');
?>
wp_enqueue_script()はwp-includes/functions.wp-scripts.phpに実装されています。デフォルトで登録されているライブラリは、wp-includes/script-loader.phpのwp_default_scripts()で確認できます。
wp_enqueue_script()のパラメータは次のようになっています。必須パラメータは$handleのみです。
wp_enqueue_script( $handle, $src, $deps, $ver, $in_footer )
- $handle:識別名
- $src:指定するライブラリのパス
- $deps:依存するライブラリの識別名を配列で記述。例:array('scriptaculous')
- $ver:ライブラリのバージョン
- $in_footer:ライブラリをwp_footer()で配置(true/false)※デフォルトはfalse
5.wp_head()
wp_head()はテーマを作成するときに必ず必要なもので、通常はhead要素の終了タグの直前に記述します。wp_head()を記述した部分に、プラグインで定義したスクリプトやスタイルのための各要素が出力されます。
wp_head()は「wp_head」フックポイントを実行するためだけの機能をもち、wp-includes/general-template.phpに実装されています。
function wp_head() {
do_action('wp_head');
}
プラグインなどでは次のように「wp_head」フックポイントに登録します。この場合はstyle要素を出力します。
<?php
/*
Plugin Name: add_style
Description: add_style
Version: 1.0
*/
function add_style() {
echo '<style type="text/css">/* ... */</style>';
}
add_action('wp_head', 'add_style');
?>
ちなみにデフォルト状態で「wp_head」フックポイントには色々なものが登録されていて、メインページでは次のような内容を出力します。
<link rel="alternate" type="application/rss+xml" title="My First Blog » フィード" href="http://user-domain/wordpress/?feed=rss2" />
<link rel="alternate" type="application/rss+xml" title="My First Blog » コメントフィード" href="http://user-domain/wordpress/?feed=comments-rss2" />
<link rel='stylesheet' id='admin-bar-css' href='http://user-domain/wordpress/wp-includes/css/admin-bar.css?ver=20110622' type='text/css' media='all' />
<script type='text/javascript' src='http://user-domain/wordpress/wp-includes/js/l10n.js?ver=20101110'></script>
<link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://user-domain/wordpress/xmlrpc.php?rsd" />
<link rel="wlwmanifest" type="application/wlwmanifest+xml" href="http://user-domain/wordpress/wp-includes/wlwmanifest.xml" />
<link rel='index' title='My First Blog' href='http://user-domain/wordpress' />
<meta name="generator" content="WordPress 3.2.1" />
<style type="text/css" media="print">#wpadminbar { display:none; }</style>
<style type="text/css" media="screen">
html { margin-top: 28px !important; }
* html body { margin-top: 28px !important; }
</style>
「wp_head」フックポイントにデフォルトで登録されているものを削除したい場合は、remove_action()を使用します。例えば
<link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://user-domain/wordpress/xmlrpc.php?rsd" />
が不要な場合は次の1行をテーマのfunctions.phpに記述します。
remove_action('wp_head', 'rsd_link');
デフォルトで「wp_head」フックポイントに登録されているアクションは、wp-includes/default-filters.phpに記述されています。下記は「wp_head」分のみ抜粋したものです。
add_action( 'wp_head', 'wp_enqueue_scripts', 1 );
add_action( 'wp_head', 'feed_links', 2 );
add_action( 'wp_head', 'feed_links_extra', 3 );
add_action( 'wp_head', 'rsd_link' );
add_action( 'wp_head', 'wlwmanifest_link' );
add_action( 'wp_head', 'index_rel_link' );
add_action( 'wp_head', 'parent_post_rel_link', 10, 0 );
add_action( 'wp_head', 'start_post_rel_link', 10, 0 );
add_action( 'wp_head', 'adjacent_posts_rel_link_wp_head', 10, 0 );
add_action( 'wp_head', 'locale_stylesheet' );
add_action( 'wp_head', 'noindex', 1 );
add_action( 'wp_head', 'wp_print_styles', 8 );
add_action( 'wp_head', 'wp_print_head_scripts', 9 );
add_action( 'wp_head', 'wp_generator' );
add_action( 'wp_head', 'rel_canonical' );
add_action( 'wp_head', 'wp_shortlink_wp_head', 10, 0 );
Movable Typeでタグのインクリメンタルサーチを実現する
Movable Typeの検索フォームを使ったタグ検索で、インクリメンタルサーチが行えるようにするカスタマイズです。
このカスタマイズを行えば、次のようにタグ文字列を1文字入力するたびに、候補を表示してくれます。ご覧のとおり、途中の文字の検索もできます。

日本語の検索も可能です。

タグのインクリメンタルサーチを導入すれば、タグクラウドのようにページを占有する必要がなくなります。タグ数が多いほど有効です。頻度の高いタグだけを表示するタグ一覧と併用するという手もあります。
ここでは「クラシックブログ」テーマに適用する方法を紹介します。
検索フォームを使ったタグ検索の動作については「Movable Typeの検索フォームでタグ検索をする」をご覧ください。
1.ライブラリのダウンロード・アップロード
「suggest.js - 入力補完ライブラリ」のページにアクセスして、「suggest.js」をダウンロードします。このライブラリはMITライセンスです(Ver2.1以降)。
ダウンロードしたsuggest.jsをブログのサイトパスにアップロードします。
2.タグリストの作成
タグのインクリメンタルサーチ用のリストを作成します。
「デザイン」→「テンプレート」→「インデックステンプレートの作成」をクリック。

次の内容を入力して「保存」をクリックし、保存後再構築を行ってください。
- タイトル:タグリスト(何でもいいです)
- 出力ファイル名:list.js
- テンプレートの内容:以下
var list = [<mt:Tags>
"<mt:TagName />"<mt:unless name="__last__">,</mt:unless></mt:Tags>
];
3.script要素の追加
「HTMLヘッダー」テンプレートモジュールの「<$mt:CCLicenseRDF$>」の直前に下記の内容を追加します。
<script type="text/javascript" src="<$mt:BlogURL$>suggest.js"></script>
<script type="text/javascript" src="<$mt:BlogURL$>list.js"></script>
<script type="text/javascript">
var start = function(){
new Suggest.Local("search",
"suggest",
list,
{ dispMax: 100, highlight: true});
};
window.addEventListener ?
window.addEventListener('load', start, false) :
window.attachEvent('onload', start);
</script>
「Suggest.Local」のパラメータの意味は次の通りです。
- 第1パラメータ:入力テキストフィールドのid属性値
- 第2パラメータ:結果表示フィールドのid属性値
- 第3パラメータ:インクリメンタルサーチの検索対象となる配列変数名
- 第4パラメータ(オプション):dispMaxは最大表示数、highlightはマッチした文字の強調表示
第4パラメータのオプションは他にもいろいろあるので、「suggest.js - 入力補完ライブラリ」のページを参照してください。
4.CSSの追加
インクリメンタルサーチの結果表示エリアのスタイルを、「スタイルシート」インデックステンプレートに追加します。赤色は「クラシックブログ」のために追加した部分です。
/* インクリメンタルサーチ結果表示エリア全体 */
#suggest {
position: absolute;
background-color: #FFFFFF;
border: 1px solid #CCCCFF;
width: 111px;
font: 13px arial,helvetica,hirakakupro-w3,osaka,"ms pgothic",sans-serif;
z-index:100;
margin-top: -3px;
}
/* 選択部分 */
#suggest div {
display: block;
width: 107px;
padding: 2px;
overflow: hidden;
white-space: nowrap;
}
/* カーソル選択時 */
#suggest div.select{
color: #FFFFFF;
background-color: #3366FF;
}
/* マウスオーバー時 */
#suggest div.over{
background-color: #99CCFF;
}
/* 強調文字 */
#suggest strong{
font-weight: bold;
color: #e50003;
}
/* 強調文字選択時 */
#suggest div.select strong{
font-weight: bold;
color: pink;
}
.widget-search {
overflow: hidden;
width: 100%;
}
.widget-search-content {
font-size: 11px;
margin: 5px 15px 20px;
}
5.検索フォームの追加
インクリメンタルサーチ用のタグ検索フォームをウィジェットに追加します。
「デザイン」→「ウィジェット」→「ウィジェットの作成」をクリック。

次の内容を入力して「保存」をクリック。
- タイトル:タグ検索(何でもいいです)
- テンプレートの内容:以下
<div class="widget-search">
<h3 class="widget-header">検索</h3>
<div class="widget-search-content">
<form method="get" action="<$mt:CGIPath$><$mt:SearchScript$>">
<input autocomplete="off" type="text" id="search" class="ti" name="tag" value="<$mt:SearchString$>" />
<mt:If name="search_results">
<input type="hidden" name="IncludeBlogs" value="<$mt:SearchIncludeBlogs$>" />
<mt:Else>
<input type="hidden" name="IncludeBlogs" value="<$mt:BlogID$>" />
</mt:If>
<input type="hidden" name="limit" value="<$mt:SearchMaxResults$>" />
<input type="submit" accesskey="4" value="検索" />
</form>
<div id="suggest" style="display:none;"></div>
</div>
</div>
<mt:If name="search_results">
<mt:IfTagSearch>
<div class="widget-tags widget">
<h3 class="widget-header">タグ</h3>
<div class="widget-content">
<ul>
<mt:Tags>
<li><a href="javascript:void(0)" onclick="location.href='<$mt:TagSearchLink encode_js="1"$>';return false;"><$mt:TagName$> (<$mt:TagCount$>)</a></li>
</mt:Tags>
</ul>
</div>
</div>
</mt:IfTagSearch>
</mt:If>
赤色がインクリメンタル検索のための追加部分です。「autocomplete="off"」はブラウザの補完機能をオフにするためのもの、form要素直後のdiv要素はインクリメンタルサーチ結果を表示するエリアです。
このサブテンプレートは「検索」ウィジェットテンプレートとほぼ同じ内容ですが、input要素の青色部分を「search」から「tag」に変更しています。
また、class属性値「widget」「widget-content」をはずしています。理由はそれらのclass属性値に設定されているpositionプロパティがインクリメンタルサーチの表示に干渉するためです。
class属性値「widget」「widget-content」をはずすとpositionプロパティ以外のプロパティもはずれてしまうので、widget-searchセレクタ、widget-search-contentセレクタで補っています。
6.検索フォームをウィジェットセットに追加
5項で作成した「タグ検索」ウィジェットを、表示したいウィジェットセットの「インストール済み」にドラッグして「保存」をクリックします。

これですべての設定が完了しましたので、全体を再構築して、タグ検索フォームでインクリメンタルサーチが動作することを確認してください。
WordPressのTwenty Elevenテーマ解説:ヘッダー (header.php):その1
WordPressの勉強も兼ねて、Twenty Elevenテーマの各テンプレートについて解説しています。確認バージョンは3.2.1です。
ヘッダー (header.php):その1
今回はヘッダーです。このエントリーでヘッダーテンプレートのすべてを紹介する予定でしたが、コードの深いところまでトレースしていくと予想以上に長くなってしまい、あきらめて数回に分けることにしました。
説明の中では、apply_filters()の役割や、_e()と__()の違い、bloginfo()とget_bloginfo()の違いなどについても触れています。
Twenty Elevenテーマの「ヘッダー (header.php)」は、スクリーンショットの赤枠で示す、WordPressのすべてのページのヘッダー部分(DOCTYPE~<div id="main">まで)に対応しています。
テンプレートのソースコードは次のとおりです。この回で説明するのは青色で示す部分です。
<?php
/**
* The Header for our theme.
*
* Displays all of the <head> section and everything up till <div id="main">
*
* @package WordPress
* @subpackage Twenty_Eleven
* @since Twenty Eleven 1.0
*/
?><!DOCTYPE html>
<!--[if IE 6]>
<html id="ie6" <?php language_attributes(); ?>>
<![endif]-->
<!--[if IE 7]>
<html id="ie7" <?php language_attributes(); ?>>
<![endif]-->
<!--[if IE 8]>
<html id="ie8" <?php language_attributes(); ?>>
<![endif]-->
<!--[if !(IE 6) | !(IE 7) | !(IE 8) ]><!-->
<html <?php language_attributes(); ?>>
<!--<![endif]-->
<head>
<meta charset="<?php bloginfo( 'charset' ); ?>" />
<meta name="viewport" content="width=device-width" />
<title><?php
/*
* Print the <title> tag based on what is being viewed.
*/
global $page, $paged;
wp_title( '|', true, 'right' );
// Add the blog name.
bloginfo( 'name' );
// Add the blog description for the home/front page.
$site_description = get_bloginfo( 'description', 'display' );
if ( $site_description && ( is_home() || is_front_page() ) )
echo " | $site_description";
// Add a page number if necessary:
if ( $paged >= 2 || $page >= 2 )
echo ' | ' . sprintf( __( 'Page %s', 'twentyeleven' ), max( $paged, $page ) );
?></title>
<link rel="profile" href="http://gmpg.org/xfn/11" />
<link rel="stylesheet" type="text/css" media="all" href="<?php bloginfo( 'stylesheet_url' ); ?>" />
<link rel="pingback" href="<?php bloginfo( 'pingback_url' ); ?>" />
<!--[if lt IE 9]>
<script src="<?php echo get_template_directory_uri(); ?>/js/html5.js" type="text/javascript"></script>
<![endif]-->
<?php
/* We add some JavaScript to pages with the comment form
* to support sites with threaded comments (when in use).
*/
if ( is_singular() && get_option( 'thread_comments' ) )
wp_enqueue_script( 'comment-reply' );
/* Always have wp_head() just before the closing </head>
* tag of your theme, or you will break many plugins, which
* generally use this hook to add elements to <head> such
* as styles, scripts, and meta tags.
*/
wp_head();
?>
</head>
<body <?php body_class(); ?>>
<div id="page" class="hfeed">
<header id="branding" role="banner">
<hgroup>
<h1 id="site-title"><span><a href="<?php echo esc_url( home_url( '/' ) ); ?>" title="<?php echo esc_attr( get_bloginfo( 'name', 'display' ) ); ?>" rel="home"><?php bloginfo( 'name' ); ?></a></span></h1>
<h2 id="site-description"><?php bloginfo( 'description' ); ?></h2>
</hgroup>
<?php
// Check to see if the header image has been removed
$header_image = get_header_image();
if ( ! empty( $header_image ) ) :
?>
<a href="<?php echo esc_url( home_url( '/' ) ); ?>">
<?php
// The header image
// Check if this is a post or page, if it has a thumbnail, and if it's a big one
if ( is_singular() &&
has_post_thumbnail( $post->ID ) &&
( /* $src, $width, $height */ $image = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), array( HEADER_IMAGE_WIDTH, HEADER_IMAGE_WIDTH ) ) ) &&
$image[1] >= HEADER_IMAGE_WIDTH ) :
// Houston, we have a new header image!
echo get_the_post_thumbnail( $post->ID, 'post-thumbnail' );
else : ?>
<img src="<?php header_image(); ?>" width="<?php echo HEADER_IMAGE_WIDTH; ?>" height="<?php echo HEADER_IMAGE_HEIGHT; ?>" alt="" />
<?php endif; // end check for featured image or standard header ?>
</a>
<?php endif; // end check for removed header image ?>
<?php
// Has the text been hidden?
if ( 'blank' == get_header_textcolor() ) :
?>
<div class="only-search<?php if ( ! empty( $header_image ) ) : ?> with-image<?php endif; ?>">
<?php get_search_form(); ?>
</div>
<?php
else :
?>
<?php get_search_form(); ?>
<?php endif; ?>
<nav id="access" role="navigation">
<h3 class="assistive-text"><?php _e( 'Main menu', 'twentyeleven' ); ?></h3>
<?php /* Allow screen readers / text browsers to skip the navigation menu and get right to the good stuff. */ ?>
<div class="skip-link"><a class="assistive-text" href="#content" title="<?php esc_attr_e( 'Skip to primary content', 'twentyeleven' ); ?>"><?php _e( 'Skip to primary content', 'twentyeleven' ); ?></a></div>
<div class="skip-link"><a class="assistive-text" href="#secondary" title="<?php esc_attr_e( 'Skip to secondary content', 'twentyeleven' ); ?>"><?php _e( 'Skip to secondary content', 'twentyeleven' ); ?></a></div>
<?php /* Our navigation menu. If one isn't filled out, wp_nav_menu falls back to wp_page_menu. The menu assiged to the primary position is the one used. If none is assigned, the menu with the lowest ID is used. */ ?>
<?php wp_nav_menu( array( 'theme_location' => 'primary' ) ); ?>
</nav><!-- #access -->
</header><!-- #branding -->
<div id="main">
1.html要素のdir属性出力
DOCTYPE宣言の下に、IEの条件付きコメントの中にlanguage_attributes()が使われています。
<!--[if IE 6]>
<html id="ie6" <?php language_attributes(); ?>>
<![endif]-->
<!--[if IE 7]>
<html id="ie7" <?php language_attributes(); ?>>
<![endif]-->
<!--[if IE 8]>
<html id="ie8" <?php language_attributes(); ?>>
<![endif]-->
<!--[if !(IE 6) | !(IE 7) | !(IE 8) ]><!-->
<html <?php language_attributes(); ?>>
<!--<![endif]-->
この関数は、次のような内容を出力します。
dir="ltr" lang="ja"
まず、dir属性の出力について解説します。
language_attributes()はwp-includes/general-template.phpに実装されています。dir属性の出力は赤色部分が対応します。
wp-includes/general-template.php
function language_attributes($doctype = 'html') {
$attributes = array();
$output = '';
if ( function_exists( 'is_rtl' ) )
$attributes[] = 'dir="' . ( is_rtl() ? 'rtl' : 'ltr' ) . '"';
if ( $lang = get_bloginfo('language') ) {
if ( get_option('html_type') == 'text/html' || $doctype == 'html' )
$attributes[] = "lang=\"$lang\"";
if ( get_option('html_type') != 'text/html' || $doctype == 'xhtml' )
$attributes[] = "xml:lang=\"$lang\"";
}
$output = implode(' ', $attributes);
$output = apply_filters('language_attributes', $output);
echo $output;
}
function_exists()はパラメータに指定した関数が定義されている場合にtrueを返却するPHPの関数です。ここではis_rtlという関数定義を判断して、定義されていれば、配列変数$attributesに「dir="rtl"」または「dir="ltr"」を設定します。
dir 属性は要素のテキストの方向性を指定するためのもので、値は次の意味をもちます。
- ltr:該当の要素のコンテンツが明示的に左から右向きに組み込まれたテキスト
- rtl:該当の要素のコンテンツが明示的に右から左向きに組み込まれたテキスト
どちらの値を設定するかは、is_rtl()で判定しています。is_rtl()はwp-includes/locale.phpの最後に実装されています。
wp-includes/locale.php
function is_rtl() {
global $wp_locale;
return $wp_locale->is_rtl();
}
話がちょっと長くなりますが、変数$wp_localeはwp-settings.phpで定義しています。
$wp_locale = new WP_Locale();
WP_Localeクラスは先程のwp-includes/locale.phpで宣言されています。
/**
* Class that loads the calendar locale.
*
* @since 2.1.0
*/
class WP_Locale {
// ...
}
ということで、is_rtl()の処理にある、
return $wp_locale->is_rtl();
は、WP_Localeクラスの中に定義されていることが分かります。
class WP_Locale {
// ...
function is_rtl() {
return 'rtl' == $this->text_direction;
}
}
変数$text_directionは同じクラス内に記述されています。値は「ltr」固定のようです。
var $text_direction = 'ltr';
この部分を「rtl」に書き換えると、ページは次のようになります。
2.html要素のlang属性出力
1項で説明したlanguage_attributes()の赤色部分でlang属性も出力します。
function language_attributes($doctype = 'html') {
$attributes = array();
$output = '';
if ( function_exists( 'is_rtl' ) )
$attributes[] = 'dir="' . ( is_rtl() ? 'rtl' : 'ltr' ) . '"';
if ( $lang = get_bloginfo('language') ) {
if ( get_option('html_type') == 'text/html' || $doctype == 'html' )
$attributes[] = "lang=\"$lang\"";
if ( get_option('html_type') != 'text/html' || $doctype == 'xhtml' )
$attributes[] = "xml:lang=\"$lang\"";
}
$output = implode(' ', $attributes);
$output = apply_filters('language_attributes', $output);
echo $output;
}
処理中で使われているget_bloginfo()はパラメータに指定した情報を取得する関数で、wp-includes/general-template.phpに実装されています。今回の該当部分のみ抜粋して掲載します。
function get_bloginfo( $show = '', $filter = 'raw' ) {
// ...
switch( $show ) {
case 'language':
$output = get_locale();
$output = str_replace('_', '-', $output);
break;
}
// ...
return $output;
}
get_bloginfo()の中で使われているget_locale()は、wp-includes/l10n.phpに実装されています。
wp-includes/l10n.php
function get_locale() {
global $locale;
if ( isset( $locale ) )
return apply_filters( 'locale', $locale );
// WPLANG is defined in wp-config.
if ( defined( 'WPLANG' ) )
$locale = WPLANG;
// If multisite, check options.
if ( is_multisite() && !defined('WP_INSTALLING') ) {
$ms_locale = get_option('WPLANG');
if ( $ms_locale === false )
$ms_locale = get_site_option('WPLANG');
if ( $ms_locale !== false )
$locale = $ms_locale;
}
if ( empty( $locale ) )
$locale = 'en_US';
return apply_filters( 'locale', $locale );
}
今回は赤色部分のコードで「ja」という文字列を返却します。理由は、WordPressの日本語パッケージではwp-config.phpに次の内容が設定されているからです。
define('WPLANG', 'ja');
次に、language_attributes()の中にあるget_option()は、管理画面の「設定」メニューの任意の項目などを取得する関数で、DBのwp_optionsテーブル(wp_が接頭辞の場合)に対応しているようです。
if ( $lang = get_bloginfo('language') ) {
if ( get_option('html_type') == 'text/html' || $doctype == 'html' )
$attributes[] = "lang=\"$lang\"";
if ( get_option('html_type') != 'text/html' || $doctype == 'xhtml' )
$attributes[] = "xml:lang=\"$lang\"";
}
ここでは、「html_type」を指定していますが、wp_optionsテーブルには該当のデータがないようなので(設定不足でしたらすいません)、変数$doctypeの値を判定します。変数$doctypeにはデフォルトで「html」が設定されているので、配列変数$attributesには「html="ja"」が設定されます。
あとは、implode()でdir属性とhtml属性を半角スペースで結合して出力します。
$output = implode(' ', $attributes);
$output = apply_filters('language_attributes', $output);
echo $output;
3.apply_filters()について
テンプレートから話がそれますが、前項の赤色のapply_filters()について解説します。
apply_filters()は「WordPressのTwenty Elevenテーマ解説:メインインデックスのテンプレート (index.php)」で解説した、do_action()を使ってフックポイントを追加する動作に似ています。apply_filters()の役割は、フィルタ(出力内容をプラグインなどで書き換える)を追加するためのものです。
例えば、
apply_filters('language_attributes', $output);
は、フックポイント「language_attributes」を追加し、書き換えの対象が$outputであることを示します。ここでは変数を1つしか設定していませんが、複数指定し、それらをフィルタの処理判定などに使うこともできます。
プラグインを作成している方はすでにご存知と思いますが、add_filter()を使えばフックポイントに任意のフィルタを追加できます。
今回の場合、プラグインで次のコードを記述すれば、フックポイント「language_attributes」、つまりapply_filters('language_attributes', $output)の実行時にbar()が起動され、html要素の最後に「class="bar"」が追加されます。
<?php
/*
Plugin Name: Bar
Description: Bar
Version: 1.0
*/
function bar($options) {
return $options . " class=\"bar\"";
}
add_filter('language_attributes', 'bar', $options);
?>
4.meta要素のcharset属性の出力
meta要素のcharset属性値の出力には、bloginfo()を利用しています。
<meta charset="<?php bloginfo( 'charset' ); ?>" />
bloginfo()はwp-includes/general-template.phpに実装されていて、先述のget_bloginfo()をキックしています。bloginfo()はget_bloginfo()の結果をechoしているのが大きな違いです。
wp-includes/general-template.php
function bloginfo( $show='' ) {
echo get_bloginfo( $show, 'display' );
}
また、bloginfo()からget_bloginfo()をキックした場合はget_bloginfo()の中でapply_filters()が動作します。厳密に言えば、キックしなくてもget_bloginfo()の第2パラメータに「display」を指定すればapply_filters()が動作します。フックポイントは「bloginfo_url」と「bloginfo」の2種類があります。
get_bloginfo()でapply_filters()が起動する部分のみ抜粋しておきます。
function get_bloginfo( $show = '', $filter = 'raw' ) {
// ...
$url = true;
if (strpos($show, 'url') === false &&
strpos($show, 'directory') === false &&
strpos($show, 'home') === false)
$url = false;
if ( 'display' == $filter ) {
if ( $url )
$output = apply_filters('bloginfo_url', $output, $show);
else
$output = apply_filters('bloginfo', $output, $show);
}
return $output;
}
$urlがtrueになる条件は、get_bloginfo()の第1パラメータが次のもの以外が設定されている場合です。
- url
- directory
- home
$urlがtrueになれば「bloginfo_url」のフィルタが登録されます。$urlがfalseになれば「bloginfo」のフィルタが登録されます(間違ってたらすいません)。
5.title要素の出力
次の部分でtitle要素を出力します。
<title><?php
/*
* Print the <title> tag based on what is being viewed.
*/
global $page, $paged;
wp_title( '|', true, 'right' );
// Add the blog name.
bloginfo( 'name' );
// Add the blog description for the home/front page.
$site_description = get_bloginfo( 'description', 'display' );
if ( $site_description && ( is_home() || is_front_page() ) )
echo " | $site_description";
// Add a page number if necessary:
if ( $paged >= 2 || $page >= 2 )
echo ' | ' . sprintf( __( 'Page %s', 'twentyeleven' ), max( $paged, $page ) );
?></title>
トップページでページ送りをしていて3ページ目であれば、次のような表示になります。
![]()
表示内容の意味は次の通りです。
ブログ名 | キャッチフレーズ | ページ番号
変数$pagedには、ページ送り(ページング)を行った場合に、URLのクエリーに設定される「paged」の値が設定されます。$pageには特に値が設定されていないようです(間違っていたらすいません)。
global $page, $paged;
内容の説明が前後しますが、先にページ番号についてまとめて説明します。ページ番号が2以上の場合に、次の部分でtitle要素に出力します。
if ( $paged >= 2 || $page >= 2 )
echo ' | ' . sprintf( __( 'Page %s', 'twentyeleven' ), max( $paged, $page
max()は、設定されたものから一番大きい値を返却するPHPの関数です。
__()は、日本語ローカライズを行うためのものです。第1パラメータにローカライズ対象の文字列、第2パラメータがドメイン名を指定します。wp-includes/l10n.phpに実装されています。
wp-includes/l10n.php
function __( $text, $domain = 'default' ) {
return translate( $text, $domain );
}
「WordPressのTwenty Elevenテーマ解説:メインインデックスのテンプレート (index.php)」で_e()について紹介しましたが、2つの関数の違いは、__()はreturnしているだけですが、_e()はechoしています。
function _e( $text, $domain = 'default' ) {
echo translate( $text, $domain );
}
wp_title()はページタイトルを表示するテンプレートタグで、利用するページで処理が異なります。
wp_title( '|', true, 'right' );
この関数はwp-includes/general-template.phpに実装されています(長いので掲載は省略)。パラメータの意味は次の通りです。
- 第1パラメータ:セパレータ文字列
- 第2パラメータ:wp_titleの実行結果をechoで表示する・しない(true/false)
- 第3パラメータ:セパレータの位置(right/left)
bloginfo('name')では、ブログ名を出力します。
bloginfo( 'name' );
管理画面の「設定」→「一般」→「キャッチフレーズ」は次の部分で出力します。
$site_description = get_bloginfo( 'description', 'display' );
if ( $site_description && ( is_home() || is_front_page() ) )
echo " | $site_description";
is_home()はサイトのトップページを表示していることを判定する関数で、wp-includes/query.phpに実装されています。
wp-includes/query.php
function is_home() {
global $wp_query;
if ( ! isset( $wp_query ) ) {
_doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
return false;
}
return $wp_query->is_home();
}
is_front_page()は、サイトのフロントページが表示されているかどうかを判定する関数で、is_home()同様、wp-includes/query.phpに実装されています。
function is_front_page() {
global $wp_query;
if ( ! isset( $wp_query ) ) {
_doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
return false;
}
return $wp_query->is_front_page();
}
is_front_page()でtrueを返却するのは、管理画面の「設定」→「表示設定」→「フロントページの表示」にて、「最新の投稿」を選択して、最新の投稿ページが表示されている場合および、「固定ページ」を選択して、「フロントページ」に指定したページが表示されている場合です。
Facebookがテストユーザー作成・編集画面をリリース
Facebookがテストユーザーの作成・編集画面をリリースしました。

これまでのテストユーザーに関する操作はAPIのみの公開でした。そのため、簡単に作成が行える「Facebookテストユーザー作成ツール」を公開しましたが、今後はFacebookの画面からテストユーザーの作成・編集が行えます。
テストユーザーはFacebookアプリを作り、アプリ管理画面から作成・編集するようになっています。Facebookアプリ作成方法については、「FacebookページにMovable TypeやWordPressの最近のブログ記事を表示する」の2項・3項や「Facebookページプロフェッショナルガイド」の96~102ページを参考にしてください。Facebookアプリを登録するのはそれほど難しい作業ではありません。テストユーザーだけを使ってみたい場合は、空のアプリ(=登録のみ)で大丈夫だと思います。
テストユーザーを使えば、自分のアカウントで「いいね!」やコメント投稿などを行ってすぐに削除するようなことをする必要がなくなります。ちなみに「Facebookのウォール投稿方法が変更」などのスクリーンショットもすべてテストユーザーを使っています。
1.テストユーザーの追加
自アカウントのアプリ一覧画面に移動。
「Roles」の右側にある「Edit Roles」をクリック。

テストユーザーを登録していない場合、「Test Users」の項目は次のようになっています。

「Test Users」の右側にある「追加」をクリック。ツールチップが表示されますが無視してください。

ダイアログが表示されるので「追加」をクリック。オプションの「Number to Add」はユーザー数(1回につき最大10ユーザー)、「Authorize this App」はアプリケーションの認証を登録時に行う・行わないの選択です。チェックしない場合は後で認証の画面を体験できます(多分)。

少し待てば「Succesfully added n(設定した数) test user!」が表示されるので、「閉じる」をクリック。

テストユーザーが追加されました。この画面で外部に一切知られずにFacebookの動作を確認することができます。具体的な動作については「Facebookテストユーザー作成ツール」の記事にまとめてますので、そちらを参照してください。

2.テストユーザーでのログイン
「切り替える」をクリック。ツールチップが表示されますが無視してください。

テストユーザーでログインできました。
3.テストユーザーの編集
「Test Users」の右側にある「Modify」をクリック。この操作はテストユーザーでログインしていない状態で行ってください。

テストユーザーの一覧が表示されます(スクリーンショットは2ユーザー登録した状態)。
名前の部分をクリックすれば名前を変更できます。

「Show Token」をクリックすれば、アクセストークンを表示します(アプリの認証を終えている必要があります)。「Login」の「切り替える」をクリックすれば、テストユーザーのログインを切り替えられます。「Make Friends」はチェックしたユーザー同士を友達にします。「削除」または×印でユーザーを削除できます。

ユーザーをチェックした状態で「Add to Other Apps」をクリックすれば、テストユーザーに他のアプリを追加することができます。

4.その他
テストユーザーでログインした状態で自アカウントのアプリ画面などに戻るには、一旦テストユーザーをログアウトし、自アカウントで再ログインする必要があるみたいです。
Movable Typeの検索フォームでタグ検索をする
Movable Typeに限らず、ブログツールやCMSにおけるタグ検索はタグクラウドや記事中のタグリンクをクリックして、同じタグの記事を表示する仕組みになっていますが、検索フォームを使ってタグ検索するカスタマイズを紹介します。
この内容は、MTQにあった質問に対する回答の一部です。以前、このブログか書籍で同じ記事を書いた記憶があるのですが、見当たらないため本エントリーで展開します。
1.カスタマイズのイメージ
タグ検索フォームを新たに作り、フォームにタグ文字列を入力して検索します。

次のようにタグ検索結果が表示され、右サイドバーにはタグの一覧も表示されます。
2.タグ検索フォーム
次のコードをMTのウィジェットとして登録します。
<div class="widget-search widget">
<h3 class="widget-header">検索</h3>
<div class="widget-content">
<form method="get" action="<$mt:CGIPath$><$mt:SearchScript$>">
<input type="text" id="search" class="ti" name="tag" value="<$mt:SearchString$>" />
<mt:If name="search_results">
<input type="hidden" name="IncludeBlogs" value="<$mt:SearchIncludeBlogs$>" />
<mt:Else>
<input type="hidden" name="IncludeBlogs" value="<$mt:BlogID$>" />
</mt:If>
<input type="hidden" name="limit" value="<$mt:SearchMaxResults$>" />
<input type="submit" accesskey="4" value="検索" />
</form>
</div>
</div>
<mt:If name="search_results">
<mt:IfTagSearch>
<div class="widget-tags widget">
<h3 class="widget-header">タグ</h3>
<div class="widget-content">
<ul>
<mt:Tags>
<li><a href="javascript:void(0)" onclick="location.href='<$mt:TagSearchLink encode_js="1"$>';return false;"><$mt:TagName$> (<$mt:TagCount$>)</a></li>
</mt:Tags>
</ul>
</div>
</div>
</mt:IfTagSearch>
</mt:If>
通常の検索フォームと異なるのは次の赤色部分のみです。
<input type="text" id="search" class="ti" name="tag" value="<$mt:SearchString$>" />
カスタマイズするのはこのタグ検索フォームだけです。検索結果はシステムテンプレートの「検索結果」をそのまま使います。
3.記事検索とタグ検索を切り替えるラジオボタンをつける
ちょっと工夫をすれば、検索フォームに記事検索とタグ検索を切り替えるラジオボタンをつけることも可能です。

次のコードをMTのウィジェットとして登録します。赤色部分が2項のソースの差分です。jQuery本体は適宜「ヘッダー」モジュールなどに追加して読み込ませてください。
<div class="widget-search widget">
<h3 class="widget-header">検索</h3>
<div class="widget-content">
<form method="get" action="<$mt:CGIPath$><$mt:SearchScript$>">
<input type="text" id="search" class="ti" name="search" value="<$mt:SearchString$>" />
<mt:If name="search_results">
<input type="hidden" name="IncludeBlogs" value="<$mt:SearchIncludeBlogs$>" />
<mt:Else>
<input type="hidden" name="IncludeBlogs" value="<$mt:BlogID$>" />
</mt:If>
<input type="hidden" name="limit" value="<$mt:SearchMaxResults$>" />
<input type="submit" accesskey="4" value="検索" />
<input type="radio" name="search_id" value="search" checked="checked" /> 記事検索
<input type="radio" name="search_id" value="tag" /> タグ検索
</form>
</div>
</div>
<script type="text/javascript">
jQuery(function() {
jQuery('input[name="search_id"]').change(function(){
jQuery('#search').attr('name', jQuery(this).val());
});
<mt:If name="search_results">
<mt:IfTagSearch>
jQuery('input[name="search_id"]').val(['tag']);
</mt:IfTagSearch>
</mt:If>
});
</script>
<mt:If name="search_results">
<mt:IfTagSearch>
<div class="widget-tags widget">
<h3 class="widget-header">タグ</h3>
<div class="widget-content">
<ul>
<mt:Tags>
<li><a href="javascript:void(0)" onclick="location.href='<$mt:TagSearchLink encode_js="1"$>';return false;"><$mt:TagName$> (<$mt:TagCount$>)</a></li>
</mt:Tags>
</ul>
</div>
</div>
</mt:IfTagSearch>
</mt:If>
検索は以下のjQueryで切り替えています。
jQuery(function() {
jQuery('input[name="search_id"]').change(function(){
jQuery('#search').attr('name', jQuery(this).val());
});
<mt:If name="search_results">
<mt:IfTagSearch>
jQuery('input[name="search_id"]').val(['tag']);
</mt:IfTagSearch>
</mt:If>
});
ラジオボタンの切り替えでchangeメソッドが起動して、input要素の値を書き換えています。
MTテンプレートタグを使っているのは、タグ検索結果ページを表示したときに、ラジオボタンがデフォルトの選択状態にせず「タグ検索」を選択した状態にするためのものです。
4.インクリメンタル検索
さらに工夫をすればタグのインクリメンタル検索が可能です。これについては別途エントリーしたいと思います。
WordPressのTwenty Elevenテーマ解説:メインインデックスのテンプレート (index.php)
WordPressの勉強も兼ねて、Twenty Elevenテーマの各テンプレートについて解説してみたいと思います。確認バージョンは3.2.1です。
メインインデックスのテンプレート (index.php)
Twenty Elevenテーマの「メインインデックスのテンプレート (index.php)」で出力されるページは次のようになります。
テンプレートのソースコードは次のとおりです。
<?php
/**
* The main template file.
*
* This is the most generic template file in a WordPress theme
* and one of the two required files for a theme (the other being style.css).
* It is used to display a page when nothing more specific matches a query.
* E.g., it puts together the home page when no home.php file exists.
* Learn more: http://codex.wordpress.org/Template_Hierarchy
*
* @package WordPress
* @subpackage Twenty_Eleven
*/
get_header(); ?>
<div id="primary">
<div id="content" role="main">
<?php if ( have_posts() ) : ?>
<?php twentyeleven_content_nav( 'nav-above' ); ?>
<?php /* Start the Loop */ ?>
<?php while ( have_posts() ) : the_post(); ?>
<?php get_template_part( 'content', get_post_format() ); ?>
<?php endwhile; ?>
<?php twentyeleven_content_nav( 'nav-below' ); ?>
<?php else : ?>
<article id="post-0" class="post no-results not-found">
<header class="entry-header">
<h1 class="entry-title"><?php _e( 'Nothing Found', 'twentyeleven' ); ?></h1>
</header><!-- .entry-header -->
<div class="entry-content">
<p><?php _e( 'Apologies, but no results were found for the requested archive. Perhaps searching will help find a related post.', 'twentyeleven' ); ?></p>
<?php get_search_form(); ?>
</div><!-- .entry-content -->
</article><!-- #post-0 -->
<?php endif; ?>
</div><!-- #content -->
</div><!-- #primary -->
<?php get_sidebar(); ?>
<?php get_footer(); ?>
1.ヘッダー情報の出力
ヘッダー情報はget_header()で出力します。
<?php
…中略…
get_header(); ?>
ヘッダー情報は、トップページの赤枠部分が対応します。
get_header()はwp-includes/general-template.phpに実装されています。
wp-includes/general-template.php
function get_header( $name = null ) {
do_action( 'get_header', $name );
$templates = array();
if ( isset($name) )
$templates[] = "header-{$name}.php";
$templates[] = 'header.php';
// Backward compat code will be removed in a future release
if ('' == locate_template($templates, true))
load_template( ABSPATH . WPINC . '/theme-compat/header.php');
}
do_action()はフックポイント「get_header」の作成を行っています。
do_action( 'get_header', $name );
プラグインを作成している方はすでにご存知と思いますが、add_action()を使えばフックポイントに任意のアクションを追加できます。
例えばプラグインで次のコードを記述すれば、フックポイント「get_header」、つまりdo_action('get_header')の実行時にfoo()が起動され、doctype宣言の前に「foo」が出力されます。
<?php
/*
Plugin Name: Foo
Description: Foo
Version: 1.0
*/
function foo() {
echo "foo";
}
add_action('get_header', 'foo');
?>
話を戻して、get_header()では、パラメータに設定した文字列をテンプレート名として利用します。「get_header('foo')」と書いておけば、「header-foo.php」を「header.php」の代わりにロードします。パラメータの設定がなければ「header.php」をロードします。
$templates = array();
if ( isset($name) )
$templates[] = "header-{$name}.php";
$templates[] = 'header.php';
2.記事の有無判定
次のif文では、記事の有無判定により処理を振り分けています。
<?php if ( have_posts() ) : ?>
// 記事が投稿されている場合の処理
<?php else : ?>
// 記事が投稿されていない場合の処理
<?php endif; ?>
have_posts()は投稿記事をチェックする関数で、wp-includes/query.phpに実装されています。
wp-includes/query.php
function have_posts() {
global $wp_query;
return $wp_query->have_posts();
}
投稿記事が存在する場合はtrue、存在しない場合はfalseを返却します。パラメータはありません。ここではhave_posts()をif文で使っていますが、この関数はループ処理で利用することもできます。
if文の中の処理の説明は後回しにして、それぞれどのような出力になるかをご覧ください。
記事が投稿されていない場合(メッセージと検索フォームを出力)
![]()
次に、それぞれの処理について解説します。
3.ナビゲーションの表示
投稿記事がある場合はナビゲーションとコンテンツを出力します。ここではナビゲーションの出力について説明します。該当する処理は次の赤色部分になります。
<?php if ( have_posts() ) : ?>
<?php twentyeleven_content_nav( 'nav-above' ); ?>
<?php /* Start the Loop */ ?>
<?php while ( have_posts() ) : the_post(); ?>
<?php get_template_part( 'content', get_post_format() ); ?>
<?php endwhile; ?>
<?php twentyeleven_content_nav( 'nav-below' ); ?>
twentyeleven_content_nav()はTwenty Elevenテーマの独自処理で、表示する記事数が1ページを超える場合に前後のナビゲーションを表示します。1ページの表示記事数は「設定」→「表示設定」→「1ページに表示する最大投稿数」で決まります。
twentyeleven_content_nav()は、テーマのfunctions.phpに実装されています。
functions.php
/**
* Display navigation to next/previous pages when applicable
*/
function twentyeleven_content_nav( $nav_id ) {
global $wp_query;
if ( $wp_query->max_num_pages > 1 ) : ?>
<nav id="<?php echo $nav_id; ?>">
<h3 class="assistive-text"><?php _e( 'Post navigation', 'twentyeleven' ); ?></h3>
<div class="nav-previous"><?php next_posts_link( __( '<span class="meta-nav">←</span> Older posts', 'twentyeleven' ) ); ?></div>
<div class="nav-next"><?php previous_posts_link( __( 'Newer posts <span class="meta-nav">→</span>', 'twentyeleven' ) ); ?></div>
</nav><!-- #nav-above -->
<?php endif;
}
「$wp_query->max_num_pages」が最大ページ数です。
さて、ナビゲーションは基本的に記事の上部と下部の2ヶ所に表示されるのですが、このテーマではトップページのみ記事の下部にだけ表示されるように仕込まれています。
この技は、style.cssにある次のセレクタを使って実現しています。
「nav-above」は記事の上部に表示するナビゲーションのid属性値で常に非表示ですが、「paged」はトップページ以外の前後ページでbody要素に与えられるclass属性値で、このときだけdiplayプロパティを「block」に変更しています。
#nav-above {
display: none;
}
.paged #nav-above {
display: block;
}
4.コンテンツの表示
ナビゲーション出力処理にはさまれて、赤色で示すコンテンツ出力処理があります。
<?php if ( have_posts() ) : ?>
<?php twentyeleven_content_nav( 'nav-above' ); ?>
<?php /* Start the Loop */ ?>
<?php while ( have_posts() ) : the_post(); ?>
<?php get_template_part( 'content', get_post_format() ); ?>
<?php endwhile; ?>
<?php twentyeleven_content_nav( 'nav-below' ); ?>
while文で、先に説明したhave_posts()を使って判定し、表示する記事があるまで繰り返します。
the_post()は投稿データをロードする関数です。the_post()を実行しただけでは何も出力しません。
余談ですが、while/have_posts()/the_post()の組み合わせは、Movable Typeの次のテンプレートタグを書いた状態とほぼ同じと言えるでしょう。
<mt:Entries>
</mt:Entries>
get_template_part()でコンテンツを出力します。get_template_part()はwp-includes/general-template.phpに実装されています。
wp-includes/general-template.php
function get_template_part( $slug, $name = null ) {
do_action( "get_template_part_{$slug}", $slug, $name );
$templates = array();
if ( isset($name) )
$templates[] = "{$slug}-{$name}.php";
$templates[] = "{$slug}.php";
locate_template($templates, true, false);
}
do_action()でフックポイント「get_template_part_スラッグ名」の作成を行っています。この場合はスラッグ名は「content」なので、フックポイント名は「get_template_part_content」になります。
また、get_header()と同様、第1パラメータと第2パラメータに設定された名前を使ってテンプレートを呼び出します。第2パラメータが設定されていれば、
「スラッグ名-名前.php」でテンプレートを呼び出します。第2パラメータが設定されていなければ、「スラッグ名.php」でテンプレートを呼び出します。
get_template_part()の第1パラメータは「content」ですが、第2パラメータには「get_post_format()」という関数名が設定されています。言い換えると、get_post_format()の実行結果が第2パラメータに設定されることになります。
<?php get_template_part( 'content', get_post_format() ); ?>
このget_post_format()は何者か?ということですが、記事の場合は投稿画面にある「フォーマット」を取得するための関数です。

get_post_format()は、wp-includes/post.phpに実装されています。
wp-includes/post.php
function get_post_format( $post = null ) {
$post = get_post($post);
if ( ! post_type_supports( $post->post_type, 'post-formats' ) )
return false;
$_format = get_the_terms( $post->ID, 'post_format' );
if ( empty( $_format ) )
return false;
$format = array_shift( $_format );
return ( str_replace('post-format-', '', $format->slug ) );
}
つまり、while文の中で実行しているget_post_format()の実行結果は、記事単位に異なります。フォーマットとget_post_format()の実行結果、対応するテンプレートは次のようになります。
| フォーマット | 実行結果 | テンプレート |
|---|---|---|
| 標準 | 0(なし) | content.php |
| アサイド | aside | content-aside.php |
| リンク | link | content-link.php |
| ギャラリー | gallery | content-gallery.php |
| ステータス | status | content-status.php |
| 引用 | quote | content-quote.php |
| 画像 | image | content-image.php |
余談ですが、テーマにあるその他の「content-xx.php」は次のように他のテンプレートに対応しています。
| テンプレート | 利用テンプレート |
|---|---|
| content-intro.php content-feature.php | showcase.php |
| content-page.php | page.php sidebar-page.php |
| content-single.php | single.php |
5.検索フォームの出力
投稿記事がなかった場合には検索フォームを出力します。
<?php else : ?>
<article id="post-0" class="post no-results not-found">
<header class="entry-header">
<h1 class="entry-title"><?php _e( 'Nothing Found', 'twentyeleven' ); ?></h1>
</header><!-- .entry-header -->
<div class="entry-content">
<p><?php _e( 'Apologies, but no results were found for the requested archive. Perhaps searching will help find a related post.', 'twentyeleven' ); ?></p>
<?php get_search_form(); ?>
</div><!-- .entry-content -->
</article><!-- #post-0 -->
_e()は、日本語ローカライズを行うためのものです。第1パラメータにローカライズ対象の文字列、第2パラメータがドメイン名を指定します。
<h1 class="entry-title"><?php _e( 'Nothing Found', 'twentyeleven' ); ?></h1>
検索フォームの出力にget_search_form()を使っています。
<?php get_search_form(); ?>
get_search_form()は、wp-includes/general-template.phpに実装されています。
wp-includes/general-template.php
function get_search_form($echo = true) {
do_action( 'get_search_form' );
$search_form_template = locate_template('searchform.php');
if ( '' != $search_form_template ) {
require($search_form_template);
return;
}
$form = '<form role="search" method="get" id="searchform" action="' . home_url( '/' ) . '" >
<div><label class="screen-reader-text" for="s">' . __('Search for:') . '</label>
<input type="text" value="' . get_search_query() . '" name="s" id="s" />
<input type="submit" id="searchsubmit" value="'. esc_attr__('Search') .'" />
</div>
</form>';
if ( $echo )
echo apply_filters('get_search_form', $form);
else
return apply_filters('get_search_form', $form);
}
テーマに「searchform.php」があればその内容を返却します。そうでない場合はget_search_form()の中で生成した検索フォームを返却します。do_action()の動作は前述と同じなので、割愛します。
6.サイドバー情報の出力
サイドバー情報は、トップページの赤枠部分が対応します。
サイドバー情報はget_sidebar()で出力します。
<?php get_sidebar(); ?>
get_sidebar()は、wp-includes/general-template.phpに実装されています。
wp-includes/general-template.php
function get_sidebar( $name = null ) {
do_action( 'get_sidebar', $name );
$templates = array();
if ( isset($name) )
$templates[] = "sidebar-{$name}.php";
$templates[] = 'sidebar.php';
// Backward compat code will be removed in a future release
if ('' == locate_template($templates, true))
load_template( ABSPATH . WPINC . '/theme-compat/sidebar.php');
}
get_sidebar()では、パラメータに設定した文字列をテンプレート名として利用します。「get_sidebar('foo')」と書いておけば、「sidebar-foo.php」を「sidebar.php」の代わりにロードします。
7.フッター情報の出力
フッター情報は、トップページの赤枠部分が対応します。
フッター情報はget_footer()で出力します。
<?php get_footer(); ?>
get_footer()は、wp-includes/general-template.phpに実装されています。
wp-includes/general-template.php
function get_footer( $name = null ) {
do_action( 'get_footer', $name );
$templates = array();
if ( isset($name) )
$templates[] = "footer-{$name}.php";
$templates[] = 'footer.php';
// Backward compat code will be removed in a future release
if ('' == locate_template($templates, true))
load_template( ABSPATH . WPINC . '/theme-compat/footer.php');
}
パラメータの設定やフックポイントの設定はこれまでと同様なので省略します。
Movable Type 5のテンプレート編集画面でタブ文字が入力できる「TextareaTabEnablerプラグイン」
Category:[自作プラグイン]
Tag:[MovableType, Plugin, TextareaTabEnabler]
Permalink
Movable Type 5のテンプレート編集画面でタブ文字が入力できる「TextareaTabEnablerプラグイン」を公開します。このプラグインはMT5.0/MT5.1で動作します。
1.機能
Movable Typeのテンプレート編集画面でタブ文字が入力できます。
タブ文字挿入前のカーソル位置

タブ文字挿入後のカーソル位置

注:このプラグインを利用する場合、「InvalidateCodeMirrorプラグイン」と併用し、CodeMirrorを無効にしてください(CodeMirrorの切り替えボタンで無効にするだけでは、本プラグインは正常に動作しません)。
2.価格
- 個人無償版/有償版での非商用利用/Movable Type Open Source:無償
- 有償版での商用利用:1050円/1サーバ(事前に動作確認してください)
無償でご利用の場合も、プラグインのご利用についてご支援・ご賛同くださる方からの寄付をお待ち申し上げます。
3.プラグインのダウンロード
下記のリンクからプラグインアーカイブをダウンロードし、任意のフォルダに保存してください。
修正履歴
2011.09.08 初版
- TextareaTabEnabler_0_10.zip(MT5.0x/MT5.1x対応)
4.プラグインのインストール
プラグインアーカイブを解凍し、pluginsフォルダ配下にあるTextareaTabEnablerフォルダをpluginsディレクトリにアップロードし、mt-static/pluginsフォルダ配下にあるTextareaTabEnablerフォルダをmt-static/pluginsディレクトリにアップロードしてください。
システム管理画面の「ツール」→「プラグイン」でプラグイン設定画面を表示し、「TextareaTabEnabler」が表示されればOKです。「InvalidateCodeMirror」も
同様にインストールしてください。

テンプレート編集画面を開き、テキストエリアでタブ文字が入力できることと、入力した内容が保存できることを確認してください。
2011.09.15
4項の説明に誤りがありましたので修正しました。
jQueryのlive関数を使ってAjaxで取得したコンテンツにイベントハンドラを登録する
jQueryのlive関数について紹介します。
live関数の使用例として、コンテンツの折りたたみをサンプルに用います。
1.コンテンツの折りたたみ
h3要素をクリックしたときに、h3要素の次にあるul要素全体を折りたたむには、次のようなjQueryのコードを記述します。実際の動作は「サンプル1」のリンク先で確認できます。
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script>
$(function() {
$("h3").click(function() {
$(this).next().slideToggle(0);
});
});
</script>
<h3>最近のブログ記事</h3>
<ul>
<li>モバイルサイトオープン</li>
<li>業務提携に関するお知らせ</li>
<li>ソリューションセミナー</li>
<li>Movable Type 入門セミナー</li>
<li>オフィシャルサイトオープン</li>
</ul>
または次のようにbind関数を利用して、clickイベントに対応するイベントハンドラを登録します。
…前略…
<script>
$(function() {
$("h3").bind('click',function() {
$(this).next().slideToggle(0);
});
});
</script>
…後略…
2.Ajax+コンテンツの折りたたみ(NG)
ところが、次のようにコンテンツ部分をAjaxで読み出すようにすると、clickイベントが効かなくなります。
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script>
$(function() {
$('#foo').load('data.txt');
$("h3").click(function() {
$(this).next().slideToggle(0);
});
});
</script>
<div id="foo"></div>
Ajaxで読み出すデータ(data.txt)
<h3>最近のブログ記事</h3>
<ul>
<li>モバイルサイトオープン</li>
<li>業務提携に関するお知らせ</li>
<li>ソリューションセミナー</li>
<li>Movable Type 入門セミナー</li>
<li>オフィシャルサイトオープン</li>
</ul>
これではAjaxで取得したデータに含まれる要素に対し、イベントハンドラ登録が行えません。このような事象を回避するためにlive関数を利用します。
3.Ajax+コンテンツの折りたたみ(OK)
live関数は、イベントハンドラ登録時に存在する要素(ここではh3要素)だけでなく、新たに発生する要素に対してもイベントが適用されます。
今回のサンプルで言えば、Ajaxで取得したデータにh3要素が含まれていれば、そのh3要素に対しても、clickイベントのイベントハンドラが有効になります。
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script>
$(function() {
$('#foo').load('data.txt');
$("h3").live('click',function() {
$(this).next().slideToggle(0);
});
});
</script>
<div id="foo"></div>
live関数の第1パラメータに指定できるイベントは下記の10種類です。
- click
- dblclick
- mousedown
- mouseup
- mousemove
- mouseover
- mouseout
- keydown
- keypress
- keyup
live関数の使い方が理解できると、jQueryをさらに活用できそうです。
PayPalでダウンロード販売する方法
PayPalのPayPalの「今すぐ購入」や「ショッピングカート」の決済後にダウンロードページなど、任意のページにリダイレクトする方法を紹介します。この方法を使えば、PayPalでダウンロード販売が行えます。
ここではPayPalの公式テストサイト「Sandbox」と「今すぐ購入」ボタンを使って紹介します。本番環境でも一部のURLを書き換えることで利用可能です。
1.ウェブペイメントの設定
決済後に任意のページにリダイレクトさせるには、管理画面の「ウェブペイメントの設定」を変更します。
「今すぐ購入」ボタンや「ショッピングカート」を提供するユーザーのPayPal管理画面で「個人設定」をクリック。マウスをポイントするとサブメニューが表示されますが無視してください。

「販売の設定」にある「ウェブペイメントの設定」をクリック。

移動先の画面で次の項目を設定します。
- 自動復帰:オン
- 復帰URL:リダイレクトするページのURLを設定します。この復帰URLはデフォルトのURLとなり、「今すぐ購入」ボタンや「ショッピングカート」作成時にSTEP3の「顧客がチェックアウト完了すると、このURLにリダイレクトされます」のテキストフィールドにURLを指定すれば、そちらが優先され、「復帰URL」は適用されません。つまり、作成したボタンごとにリダイレクトのページを指定可能です。逆に、「復帰URL」を複数のボタンに対応させるには、「復帰URL」のページで支払いデータを読み込んで、処理を振り分けることで可能になると思います。
- 支払いデータ転送:オン
![]()
保存すると「IDトークン」が表示されます。
![]()
この「IDトークン」は一度保存すると「支払いデータ転送」の項目に常に表示されるようです。

2.文字コードの変更
決済後にリダイレクト先のページに転送する情報の文字コードを、リダイレクト先のページを提供するブログなどの文字コードに合わせます。
「個人設定」をクリック。

「言語のエンコード」をクリック。

「詳細オプション」をクリック。

今回ウェブサイトで使用している文字エンコーディングは「UTF-8」なので「エンコード方式」から「UTF-8」を選択します。また、「PayPalから送信されたデータと同じエンコード方式を使用しますか」は「いいえ」を選択して、さきほどと同様「UTF-8」を選択し、「保存」をクリック。

3.リダイレクトページの作成
PayPalでは次のようなサンプルが公開されています(若干修正しています)。他にもPerl/ASP/VBScript/ColdFusion版があります。
- PayPal - 即時支払い通知のコードサンプル(要ログイン)
<?php
// read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-synch';
$tx_token = $_GET['tx'];
$auth_token = "IDトークン";
$req .= "&tx=$tx_token&at=$auth_token";
// post back to PayPal system to validate
$header .= "POST /cgi-bin/webscr HTTP/1.0\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
$fp = fsockopen ('www.sandbox.paypal.com', 80, $errno, $errstr, 30);
// If possible, securely post back to paypal using HTTPS
// Your PHP server will need to be SSL enabled
// $fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);
if (!$fp) {
// HTTP ERROR
} else {
fputs ($fp, $header . $req);
// read the body data
$res = '';
$headerdone = false;
while (!feof($fp)) {
$line = fgets ($fp, 1024);
if (strcmp($line, "\r\n") == 0) {
// read the header
$headerdone = true;
} else if ($headerdone) {
// header has been read. now read the contents
$res .= $line;
}
}
// parse the data
$lines = explode("\n", $res);
$keyarray = array();
if (strcmp ($lines[0], "SUCCESS") == 0) {
for ($i=1; $i<count($lines);$i++){
list($key,$val) = explode("=", $lines[$i]);
$keyarray[urldecode($key)] = urldecode($val);
}
// check the payment_status is Completed
// check that txn_id has not been previously processed
// check that receiver_email is your Primary PayPal email
// check that payment_amount/payment_currency are correct
// process payment
$firstname = $keyarray['first_name'];
$lastname = $keyarray['last_name'];
$itemname = $keyarray['item_name'];
$amount = $keyarray['payment_gross'];
echo ("<p><h3>Thank you for your purchase!</h3></p>");
echo ("<b>Payment Details</b><br>\n");
echo ("<li>Name: $firstname $lastname</li>\n");
echo ("<li>Item: $itemname</li>\n");
echo ("<li>Amount: $amount</li>\n");
echo ("");
} else if (strcmp ($lines[0], "FAIL") == 0) {
// log for manual investigation
}
}
fclose ($fp);
?>
取引が完了しましたので、購入商品の受領書をメールでお送りしました。<br> <a href='https://www.paypal.com'>www.paypal.com</a> からアカウントにログインし、取引の詳細を見ることができます。<br>
2項で表示されたIDトークンを、赤色で示している$auth_tokenの右辺に設定します(下に表示しているのはデタラメに入力した文字列ですが、設定イメージはこんな感じです)。
$auth_token = "fasf9ajafBsp9jasFa9w873thLgqa09gauSWghjwtqoj3r0ugaOjQ309ufa";
fsockopenは、Sandboxで接続する場合の設定にしています。
$fp = fsockopen ('www.sandbox.paypal.com', 80, $errno, $errstr, 30);
本番環境で利用する場合は、青色の内容に修正してください。
$fp = fsockopen ('www.paypal.com', 80, $errno, $errstr, 30);
SSLで接続する場合は、前述のfsockopenの行をコメントアウトして、コメントアウトされている次の行を利用します(行頭の//を削除)。
// $fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);
この部分も、本番環境で使用する場合は「www.sandbox.paypal.com」を「www.paypal.com」に直してください。
キモになる「支払いデータ」は次の部分で処理しています。
if (strcmp ($lines[0], "SUCCESS") == 0) {
for ($i=1; $i<count($lines);$i++){
list($key,$val) = explode("=", $lines[$i]);
$keyarray[urldecode($key)] = urldecode($val);
}
// check the payment_status is Completed
// check that txn_id has not been previously processed
// check that receiver_email is your Primary PayPal email
// check that payment_amount/payment_currency are correct
// process payment
$firstname = $keyarray['first_name'];
$lastname = $keyarray['last_name'];
$itemname = $keyarray['item_name'];
$amount = $keyarray['payment_gross'];
このサンプルコードを、2項で指定した文字エンコーディングで保存し、「復帰URL」で指定したファイル名で保存・アップロードします。アップロード先と「復帰URL」が一致するようにしてください。
4.購入のテスト
この設定状態で、購入者のテストアカウントを使って「今すぐ購入」をクリック。

購入確認画面で「今すぐ支払う」をクリック。
自動復帰を「オン」に設定していれば次の画面に遷移します。

サンプルコードの画面に自動的にリダイレクトします。あとはサンプルページにダウンロードのリンクを追加すれば完了です。
PayPalから転送される文字エンコーディングとページのエンコーディングが一致していないと、商品名「ほげほげ」の部分が文字化けします(確認済み)。
ウェブペイメントの「支払いデータ転送」をオフにして購入すると、サンプルでは「取引が完了しました~」の部分しか表示されませんでした。つまり、「支払いデータ」はName/Item/Amountの部分が対応しているということです。
5.その他
これまでの設定で、ダウンロードページまでのリダイレクトは完了です。サンプルページの(X)HTMLマークアップやスタイルをきちんと直せば、ある程度使い物になると思います。
これ以外に、リダイレクトページに遷移する前に購入ユーザーがブラウザを終了させた場合に対応する「即時支払い通知(IPN)」の設定が必要ですが、それは別途エントリーしたいと思います。
Movable Typeのカテゴリリストにダミーの親カテゴリを表示する
Movable Typeのカテゴリリストにダミーの親カテゴリを表示するカスタマイズを紹介します。
1.カスタマイズのイメージ
まず、次のようなカテゴリ構成を想定します。
アメリカ
└ ニューヨーク
カナダ
└ バンクーバー
日本
└ 東京
中国
└ 北京
韓国
└ ソウル
このカテゴリ構成について、親カテゴリのみを次のように「北米」「アジア」などの地域名でグルーピング表示するように変更します。
北米
├ アメリカ
└ カナダ
アジア
├ 日本
├ 中国
└ 韓国
「アメリカ」「日本」などの親カテゴリのURLは変更しません。つまり「北米」「アジア」はカテゴリとして追加するのではなく、元のカテゴリをまとめるためだけに付与するタイトルです。
2.カスタマイズ
各親カテゴリの説明欄に、グルーピングしたい地域名を設定します。念のため子カテゴリの説明欄には何も設定しないでください。
「カナダ」の場合

「日本」の場合

設定後、次のようなサブテンプレートを作成します。
<mt:TopLevelCategories>
<mt:if tag="CategoryDescription">
<$mt:CategoryDescription setvar="area"$>
<mt:SetVarBlock name="list{$area}" append="1">
<li>
<a href="<$mt:CategoryArchiveLink$>"title="<$mt:CategoryDescription remove_html="1" encode_html="1"$>"><$mt:CategoryLabel$></a>
</li>
</mt:SetVarBlock>
</mt:If>
</mt:TopLevelCategories>
<mt:loop name="list">
<h2><mt:GetVar name="__key__"></h2>
<ul><mt:GetVar name="__value__"></ul>
</mt:loop>
これを再構築すれば、次のように表示されると思います。

3.サブテンプレートの説明
まず、MTTopLevelCategoriesタグで親カテゴリの一覧を取得します。次にMTIfタグを使って、カテゴリの説明欄に設定がある場合のみ、MTCategoryDescriptionタグの内容を変数areaに保持します。そして変数areaの値をハッシュ変数listのキーとして使い、ハッシュの値にカテゴリ名を設定します。
例えば「カナダ」カテゴリは、ハッシュ変数listに次のような感じで設定されます(イメージです)。
list{"北米"} = "<li><a href="...">カナダ</a></li>"
さらに「アメリカ」カテゴリは次のようにlist{"北米"}に追加されます。追加されるのは、MTSetVarBlockタグに「append="1"」を使って、追記するよう指定しているためです。
list{"北米"} = "<li><a href="...">カナダ</a></li><li><a href="...">アメリカ</a></li>"
同じように、「日本」「中国」「韓国」は次のように設定されます。
list{"アジア"} = "<li><a href="...">日本</a></li><li><a href="...">中国</a></li><li><a href="...">韓国</a></li>"
あとは、MTLoopタグとMTGetVarタグを使ってハッシュ変数areaを出力すれば完成です。
このカスタマイズはMT4/MT5で使えます。MT5.1であればデフォルト機能のカテゴリの並び替えを行うことで、並び替えた順番で表示することができます。
4.カテゴリの説明欄が使えない場合
カテゴリの説明欄を他の用途ですでに使っていて、今回のカスタマイズで使えない場合は、カテゴリ用のカスタムフィールドを追加し、そこに地域名を設定して利用する方法があります。
Facebookのウォール投稿方法が変更
Facebookのウォール投稿方法が変更されました。ということで変更点についてまとめてみました。この記事は2011年9月4日現在の内容です。
1.投稿フォーム
変更前は次のようなフォーム画面だったと思います。

変更後は次のようなフォーム画面になり、「リンク」「動画」のアイコンがなくなりました。

2.追加機能
変更直後に投稿しようとすると、次のような画面が表示されます。それにしたがって追加機能をざっくり説明します。
一緒にいる人のタグ付けが行えます。

アイコンをクリックすると「誰と一緒にいる?」という欄が表示されるので、一緒にいる人の名前を入力します。もう一度クリックすると非表示になります。

位置情報の追加が行えます。

アイコンをクリックすると「今どこにいる?」という欄が表示されるので、場所を入力します。もう一度クリックすると非表示になります。

投稿時・投稿後のプライバシー設定が行えます。説明によると、「公開」がこれまでの「すべてのユーザー」に該当するようです。

アイコンをクリックすると、次のように公開範囲を選択できます。「公開」の丸いアイコンは地球のようです。

3項以降は上記以外の変更点についてまとめました。
3.改行挿入でShiftが不要
これまでは改行するために「Shift+リターン」を行っていましたが、Shiftなしのリターンでも改行できるようです(Shiftありでも改行します)。
以前からそのようになっていたら単なる勘違いです。すいません。
4.リンクの挿入方法
「リンク」のアイコンがなくなりましたが、テキストエリアにURLを入力すればこれまでと同じ動作になるようです。
手入力の場合、URL入力までは何も反応しません(カーソルの位置に注目してください)。

改行するとリンクが表示されます。

URLをペーストした場合、改行なしでリンクが表示されます(カーソルの位置に注目してください)。

「http://~/」でも同じです。

リンクが表示されたら、入力したURLは不要なので削除します。

こんな感じで投稿されます。

URLは途中で入力しても反応してくれます。

5.投稿の削除
2011/09/07追記:以下の記載内容はTest Userを使って確認した動作です。通常のユーザーにはこれまで通り×印が表示されています。
投稿の削除は、変更前は×印をクリックしていましたが、変更後は×印がなくなりました。その代わり、同じ位置に表示されるアイコンをクリックし、メニューから「投稿を削除」をクリックすることで削除できます。

6.動画のアップロード
動画のアップロードはできなくなったようですが、Facebookページでは可能なようです。「写真を追加」のリンクから行えます。
docomoのスマートフォンを徹底的に安く利用する(その後)
「docomoのスマートフォンを徹底的に安く利用する」でエントリーしたとおり、2011年7月末に購入したスマホをWiMAXと組み合わせて、docomoの月額使用料金を1050円にしようともくろみました。
使い始めて1ヶ月ちょっと経ちましたので、docomoの8月分の利用料金(9月請求額)を公開します。
結果から申し上げますと、8月の利用料金は1518円でした。6月までの使用料は7800円、7月は端末購入サポート解除料2400円が加算されて約10000円だったのでかなり安く抑えられました。

1518円の内訳です。
1050円を超えてしまった理由は次のとおりです。
- Uスタンダードプランを使っている(moperaメール用のため解約せず):+500円
- ケータイ保障に入っている:+380円
ただし、
- ISPセット割:-300円
- ケータイ保障の初回割引:-184円
で、プラスマイナス396円が加算されています。これに消費税がかかって1518円です。9月利用分はケータイ保障の割引がないので+184円になる予定です。
実際には以下の契約のみにすれば1050円(税込みで1100円位)になると思います。
| 契約内容 | 月額 |
|---|---|
| FOMAタイプシンプルバリュー | 743円 |
| 付加機能使用料(spモード) | 300円 |
| ユニバーサルサービス料 | 7円 |
| 計 | 1050円 |
使っているWiMAX(So-net)は実質月額3880円なので、スマホに必要な8月の使用料は3880円+1518円=5398円と、これまでより約2500円安くなりました。
WiMAXはスマホだけでなく外出時のPCでも使っています。これまで家でしかできなかったメールチェックやインターネットもできるようになったので、安くなったことに加え、非常に便利になりました。
WiMAXなどの高速データ通信サービスは、2年縛りなどで探せばより安いプランがあると思います。
ということで、docomoのスマホを安く使ってみたい方の参考になれば幸いです。
PayPalの公式テスト環境「Sandbox」について(その2:「今すぐ購入」のテスト)
「PayPalの公式テスト環境「Sandbox」について(その1:アカウント作成)」の続きで、今回はテストアカウントを使って「今すぐ購入」のテストを行ってみました。
1.テストアカウントでのログイン
テストアカウントでのログインは、次の手順になります。
テストアカウントを作成した元のアカウントで「Sandboxのページ」にログイン

「Test Accounts」をクリック。

ログインしたいユーザーを選択して、「Enter Sandbox Test Site」をクリック。

ログイン用のウィンドウが開くので、同じテストアカウントでログイン。

ログインできました。
管理画面が日本語になっていない場合は、右側のドロップダウンより「日本語(Japanese)」を選択。日本語にするには、テストアカウント作成時(preconfigured accountで作成)に、「Country」から「Japan」を選択している必要があります。

テストアカウント画面は、「PayPal Sandbox」というSandboxの画面の中に本来の「PayPal」という管理画面が表示されています。

2.テストアカウントの切り替え
PayPalのテストアカウント画面右上には、右上にある元のアカウントのログアウトボタンと、その左下にテストアカウント用のログアウトボタンが表示されています。

右上の「ログアウト」をクリックすると、元アカウントのログアウトを行ってしまい、テストアカウントを切り替えるにはSandboxのログインからやり直す必要があります。テストアカウントの切り替えるには、その左下にある(テストアカウントの)「ログアウト」をクリックすると良いでしょう。
3.販売者テストアカウントで「今すぐ購入」ボタンの作成
販売者テストアカウントでログインし、管理画面で「今すぐ購入」ボタンを作ります。セッションが短いので、操作中にログアウトしてしまったら再度ログインしてください。
「決済サービス」をクリック。

「PayPal ウェブ ペイメント スタンダード」の「[今すぐ購入]ボタン」をクリック。

ステップ1で次の項目を設定します。
- ボタンタイプ:今すぐ購入
- 商品名:任意の商品名
- 商品ID:任意の商品ID
- 価格:任意の価格(税抜き)
- 通貨:JPY
- 税金:5%
ステップ2はとりあえず「PayPalにボタンを保存する」だけチェックします。保存したボタンは、ステップ1の「ボタンタイプの選択」のすぐ下にある「[保存したボタン] に移動」のリンクから選択できます。
ステップ3ではキャンセル時の遷移ページのURL、チェックアウト時の移動ページのURLを設定します。ステップ3は設定しなくても大丈夫ですが、動作確認のために設定しています。
コードが生成されました。ブログまたは手作業でテストページなどを作り、生成されたコードを貼り付けます。

4.購入者テストアカウントで「今すぐ購入」ボタンを使った購入
3項とは別のブラウザで購入ページを表示し、購入ボタンをクリック(同じブラウザでも大丈夫だと思いますが念のため)。

購入ページが表示されました。購入者テストアカウントでログインします。
購入内容を確認して「今すぐ支払う」をクリックします。STEP3でうっかり設定していたメッセージボックス「売り手への特別な指示を追加:」は赤枠部分に表示されています。
購入が完了しました。「勇次郎 荒木's Test Storeに戻る」に、STEP3で入力したチェックアウト時のリンクが設定されていました。
5.取引の確認
取引が正常に行われたことを確認します。まず、販売者の「マイアカウント」をクリックすると取引が行われたことが分かります。
次に、購入者の「マイアカウント」をクリックすると取引が行われたことが分かります。
メール送信内容を確認するには、Sandboxの「Test Email」をクリック。

販売者へのメールと購入者へのメールが送信されています。リンクをクリックすればメールの内容も確認できます。
6.チェックアウト時の移動ページ
チェックアウト時の移動ページ(「勇次郎 荒木's Test Storeに戻る」をクリック)は次のようになります。
このページはPayPalで提供されている以下のURLにあるPHPのサンプルを利用しています。このページはPayPalにログインしていないと表示されません。あしからず。
なお今回の動作確認では、このサンプルは正常に動作していません。
管理画面の設定変更とこのサンプルを組み合わせることで、ダウンロードページにリダイレクトできるようです。それについては別途エントリーしたいと思います。
MTのウェブサイトでブログ記事が作れる小粋空間版「Movable Type」の配布開始
Movable Typeはバージョン5から「ウェブサイト」という概念を導入し、サイト制作の利便性が向上しましたが、その反面、ブログだけを作成する場合には「空の」ウェブサイトを作る必要があります。
ということで、Movable Type Open Sourceをベースにソースコードを改変し、ウェブサイトでブログ記事が作れる機能を追加した小粋空間版「Movable Type」を当ブログで配布致します(MTOSのGPLにもとづいた再頒布です)。
下のスクリーンショットは小粋空間版「Movable Type」で作ったウェブサイトのトップページです。ウェブサイトのブログ記事が並んでいます。
小粋空間版「Movable Type」は下記のリンクからダウンロードできます。バージョン番号はMovable Typeの現在の最新バージョンにあわせています。
以下、主な機能を紹介します。ウェブサイトでブログ記事を管理できる以外の変更は行っていません。
1.ブログ記事の投稿
ウェブサイトでブログ記事の投稿が行えます。

グローバルナビゲーションの「新規作成」からもブログ記事の新規作成が行えます。

2.カテゴリの作成
ウェブサイトでカテゴリが作成可能です。ブログ記事編集画面でもカテゴリを作成できます。

3.アーカイブパスの設定
ウェブサイトの全般設定画面でアーカイブURL・アーカイブパスの設定が行えます。

4.優先アーカイブタイプの設定
ウェブサイトの全般設定画面で優先アーカイブタイプの設定が可能です。

5.ブログ記事一覧画面
ウェブサイトのブログ記事一覧で、自ウェブサイトのブログ記事を表示します。
自ウェブサイトのブログ記事だけを表示するフィルタも用意しています。

システム管理画面のブログ記事一覧にもウェブサイトのブログ記事を表示します。
6.ダッシュボード
ウェブサイトのダッシュボードに「Blog Stats」を表示します。

7.テーマ
テーマ「クラシックブログ(ウェブサイト用)」を追加しました。このテーマを選択すれば、ウェブサイトでブログ記事テンプレート、ブログ記事リストテンプレートが使えます。

8.ブログ記事のエクスポート・インポート
ウェブサイトでブログ記事のエクスポート・インポートが行えます。

9.注意事項
MT本体のバージョンアップが行われたときにはこちらも追従する予定でいますが、動作保障はありませんので予めご了承ください。
10.リリースノート
MT3やMT4からのアップグレード(=1番目に作ったブログをウェブサイトとして割り当てる)には対応していません。


