この記事は年以上前に書かれたもので、内容が古かったり、セキュリティ上の問題等の理由でリンクが解除されている可能性があります。
WordPressに標準装備されているウィジェットで、自作のウィジェットを作成してみよう、という内容です。便利な機能で、クライアントワークでは割と必須ですけどあまり情報がない印象だったので復習をかねて書いてみました。
WPのウィジェットに追加できるアイテムボックスを自作する、という方法です。基本的な事しか書いてません。なので、WordPressテーマ開発のビギナーさん向けになります。
ウィジェットをテーマで使えるようにする
まずはおさらい。利用しているテーマでウィジェットを使えるようにするには、その為のコードを書く必要があります。

何もしていない状態ですと、上記のようにウィジェットページには注意文しか表示されません。
まずは利用可能にする
利用するためには以下のようなコードを利用中のテーマファイル内にあるfunctions.phpに書きます。
if ( function_exists('register_sidebar') )
register_sidebar();
これで、先ほどのウィジェットページが以下のようになります。

ドラッグ&ドロップでウィジェットを追加すれば、手軽にWebサイトにコンテンツを追加できますね。表示させる順番もドラッグ&ドロップするだけ。こんな便利な物を使わない手はありませんね。
テーマファイルにもコードが必要
でも、このままではWebサイトには何も表示されません。ウィジェットを表示させるエリアを指定する必要があります。
そこで、以下のようなコードをテーマファイルに含めます。
<?php dynamic_sidebar(); ?>
これで、Webサイトにウィジェットに追加した項目が表示されるようになりました。

何も無いところに表示されました。
複数登録する
では、複数のエリアで使用したい場合はどうするのでしょう。その場合は別のウィジェットエリアをもう一度登録しなくてはなりません。先ほどfunctions.phpに書いたコードに追加してみます。
if ( function_exists('register_sidebar') )
register_sidebar();
/*ここまではさっき書いたコード*/
/*ここから2つ目のウィジェット*/
register_sidebar(array(
'name' => '2つ目のウィジェット',
'id' => 'foo',
'before_widget' => '<div>',
'after_widget' => '</div>',
'before_title' => '<h3>',
'after_title' => '</h3>'
));
なにやらいろいろ増えちゃいました。もしかして複数登録って面倒くさいんでしょうか。
本当は以下のように同じコードで2つ目のウィジェットは追加できます。
register_sidebar(); register_sidebar(2);
で、テーマファイルも数字を入れればいいだけ。
<h1>ウィジェット1つ目</h1> <?php dynamic_sidebar(); ?> <h1>ウィジェット2つ目</h1> <?php dynamic_sidebar(2); ?>
ただ、これだとエリア箇所が増えた際に管理者が混乱する可能性があります。
ですので、先ほどのように任意の名前とidを含める等、配列までお手入れする癖を付けておくと良さそうです。

こうすれば管理者が分かりやすいですよね。
でも、やはりこれだけだと、Webサイトには表示されません。先ほどと同じ手順で、テーマファイル内にウィジェットを表示させるエリアを作ってあげないといけません。
IDをあわせる
2つ目はIDを指定しました。
'id' => 'foo',
このIDに合わせてコードをテーマファイルに書きます。
<?php dynamic_sidebar('foo'); ?>
これで2つ目のウィジェットエリアが追加できました。

おさらいはここまでです。
[note]実践では条件分岐なども必要になりますが、ググれば山のように出ますので適当に調べてください。[/note]
では、このウィジェットに追加するアイテムを自作してみます。
オリジナルのウィジェットアイテムを作る
やっと本題。このウィジェットエリアに登録できるアイテムを自作します。そうする事で、管理者は知識不要で好きな箇所に好きなときに好きにコンテンツを管理する事が出来ます。
こういった機能は「CMS」なら当たり前の機能ですので、WordPressをブログエンジンではなくCMSとして利用するならウィジェット機能を強化する方法は覚えて置いて損は無いと思います。
とにかく作ってみる
とりあえずシンプルに自由に何でも書けるテキストエリアを追加してみます。
※デフォルトで既に存在していますが気にしないで下さい。
class MyWidgetItem extends WP_Widget {
function MyWidgetItem() {
parent::WP_Widget(false, $name = 'ウィジェットの名前');
}
function widget($args, $instance) {
extract( $args );
$title = apply_filters( 'widget_title', $instance['title'] );
$body = apply_filters( 'widget_body', $instance['body'] );
?>
<li <?php echo 'id="foo"'; ?> >
<?php if ( $title ) ?>
<?php echo $before_title . $title . $after_title; ?>
<?php echo '<p>' . $body . '</p>'; ?>
</li>
<?php
}
function update($new_instance, $old_instance) {
$instance = $old_instance;
$instance['title'] = strip_tags($new_instance['title']);
$instance['body'] = trim($new_instance['body']);
return $instance;
}
function form($instance) {
$title = esc_attr($instance['title']);
$body = esc_attr($instance['body']);
?>
<p>
<label for="<?php echo $this->get_field_id('title'); ?>">
<?php _e('サイトに表示されるコンテンツ:'); ?>
</label>
<input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo $title; ?>" />
</p>
<p>
<label for="<?php echo $this->get_field_id('body'); ?>">
<?php _e('サイトに表示されるコンテンツ:'); ?>
</label>
<textarea class="widefat" rows="16" colls="20" id="<?php echo $this->get_field_id('body'); ?>" name="<?php echo $this->get_field_name('body'); ?>">
<?php echo $body; ?>
</textarea>
</p>
<?php
}
}
add_action('widgets_init', create_function('', 'return register_widget("MyWidgetItem");'));
このコードをfunctions.phpに書くと

このように自作したウィジェットアイテムが表示され、他のアイテムと同様に、好きなエリアに好きなコンテンツを手軽に追加出来る様になりましたね。今回はタイトルと、任意のコンテンツを追加出来る様になる、というウィジェットアイテムを作成してみました。
以下、解説的なもの。ウィジェットで使えるようにした項目は$bodyと、$titleという変数で管理しています。この変数がどのように渡されているかを見ればウィジェットからWebサイトへの表示までの流れを把握できるかと思います。

こんな感じ(多分)。最終的にwidgets_initアクションフックで登録します。
テンプレ的にしてみる
上記を理解して頂いた上で、Boilerplate的なものを書いてみます。
class MyWidgetItem extends WP_Widget {
function MyWidgetItem() {
parent::WP_Widget(false, $name = 'ウィジェット名');
}
function widget($args, $instance) {
extract( $args );
$example = apply_filters( 'widget_example', $instance['example'] );
?>
<li <?php echo 'id="example"'; ?> >
<?php echo '<p>' . $example . '</p>'; ?>
</li>
<?php
}
function update($new_instance, $old_instance) {
$instance = $old_instance;
$instance['example'] = trim($new_instance['example']);
return $instance;
}
function form($instance) {
$example = esc_attr($instance['example']);
?>
<p>
<label for="<?php echo $this->get_field_id('example'); ?>">
<?php _e('入力項目:'); ?>
</label>
<textarea class="widefat" rows="16" colls="20" id="<?php echo $this->get_field_id('example'); ?>" name="<?php echo $this->get_field_name('example'); ?>">
<?php echo $example; ?>
</textarea>
</p>
<?php
}
}
add_action('widgets_init', create_function('', 'return register_widget("MyWidgetItem");'));
exampleという項目でWebサイトに追加出来る様にしました。ウィジェットアイテムの名前は「ウィジェット名」となっています。テキストエリアで書いたものはreturn $instance;で保存され、pタグ内に出力されます。
メリット
先ほども書きましたが、ウィジェットでコンテンツを手軽に追加できる、という仕様はCMS施工にとても便利です。

クライアントさん側でコンテンツの変更が出来ますし、例えばセールやキャンペーンの際に順番を変えて目立たせたり、という事も出来ますので、管理モチベーションも上がりやすいかもしれません。
また、FlickrやTumblrなどを、ユーザーIDを入れるだけで表示出来るようにしたり、RSSフィードを流したり、この前書いたように地名だけでGoogleマップを表示させたり、などなど、色々とアイデアが湧いてきます。ボックス要素で包括してclass名を変更出来る様にすれば、CSSやJSやテーマファイル側で頑張らなくてもレイアウトの調整やデザインの変更が手軽に出来ます。また、functions.phpに別のコードを書くことでウィジェットでショートコードを使えるようにもなります。
先ほどのテンプレは、入力する、保存する、反映させる、という基礎的な項目が含まれていますので色々とカスタマイズしてみてください。
以上、自作ウィジェットの作成Tipsでした。ツッコミどころもあるかもですけど、出来るだけ分かりやすく書いたつもりです。尚、ドキュメントは以下になります。
[追記]
「普通はプラグインにする」という意見を頂きましたが、何が普通なのか、というのが僕には分かりませんので管理しやすい方法でいいんじゃないかなと思います。それから、冒頭にも「テーマ開発」と書いていますので、記事に関しては配布されているテーマを弄る事を念頭に入れていません。

