
WordPressテーマに自作のウィジェット機能を付加する方法がないかと探したら、あまりなかったので自分が作成した方法をメモがてら紹介です。
プラグインとして追加するものは、検索で結構見つかるのですが、、今回はテーマに追加する形になります。(この方法は、子テーマに書いても有効な方法です。)
photo by Chris Harrison
目次
作成するウィジェット
今回作成するウィジェットは、このような感じにしたいと思います。

仕様としてはこんな感じ。
- 画像(75×75)付きの新着エントリーを表示する
- ウィジェットのタイトルを変更できるようにする
- 表示数も変更できるようにする
ウィジェット設定画面の見た目はこんな感じになります。

準備
まずは作成前の準備です。
といっても、アイキャッチがなかったときのために、以下のような画像に「no-image.png」と名前をつけて(親)テーマのimagesフォルダーに放り込むだけです。

あとこちらの記事を読んでおくと、以降の文の理解が深まると思います。今回のコードはこちらを参考にさせていただきました。
WordPressのウィジェットを自作するためのTips – かちびと.net
ウィジェット作成クラスを作る
ウィジェット作成するためのコードは、functions.phpに記入していきます。
僕はこのように書きました。ポイントとなるコードの説明はコメントに書いてあります。
///////////////////////////////////////////////////
//新着エントリーウィジェットの追加
///////////////////////////////////////////////////
class NewEntryWidgetItem extends WP_Widget {
function NewEntryWidgetItem() {
parent::WP_Widget(false, $name = '新着エントリー');//ウィジェット名
}
function widget($args, $instance) {
extract( $args );
//タイトル名を取得
$title_new = apply_filters( 'widget_title_new', $instance['title_new'] );
//表示数を取得
$entry_count = apply_filters( 'widget_entry_count', $instance['entry_count'] );
//表示数をグローバル変数に格納
//後で使用するテンプレートファイルへの受け渡しよ
//(もうちょっとスマートな方法があるのかも)
global $g_entry_count;
$g_entry_count = 5;//表示数が設定されていない時は5にする
if ($entry_count) {//表示数が設定されているときは表示数をグローバル変数に代入
$g_entry_count = $entry_count;
}
?>
<?php //classにwidgetと一意となるクラス名を追加する ?>
<div id="new-entries" class="widget widget_new_popular">
<h4><?php if ($title_new) {
echo $title_new;//タイトルが設定されている場合は使用する
} else {
echo '新着エントリー';
}
?></h4>
<?php
//新着エントリー表示用の処理を書くところだけど
//コード量も多く、インデントが深くなり読みづらくなるので
//テンプレートファイル側に書く
get_template_part('new-entries'); ?>
</div><!-- /#new-entries -->
<?php
}
function update($new_instance, $old_instance) {
$instance = $old_instance;
$instance['title_new'] = strip_tags($new_instance['title_new']);
$instance['entry_count'] = strip_tags($new_instance['entry_count']);
return $instance;
}
function form($instance) {
$title_new = esc_attr($instance['title_new']);
$entry_count = esc_attr($instance['entry_count']);
?>
<?php //タイトル入力フォーム ?>
<p>
<label for="<?php echo $this->get_field_id('title_new'); ?>">
<?php _e('新着エントリーのタイトル'); ?>
</label>
<input class="widefat" id="<?php echo $this->get_field_id('title_new'); ?>" name="<?php echo $this->get_field_name('title_new'); ?>" type="text" value="<?php echo $title_new; ?>" />
</p>
<?php //表示数入力フォーム ?>
<p>
<label for="<?php echo $this->get_field_id('entry_count'); ?>">
<?php _e('表示数(半角数字)'); ?>
</label>
<input class="widefat" id="<?php echo $this->get_field_id('entry_count'); ?>" name="<?php echo $this->get_field_name('entry_count'); ?>" type="text" value="<?php echo $entry_count; ?>" />
</p>
<?php
}
}
add_action('widgets_init', create_function('', 'return register_widget("NewEntryWidgetItem");'));
本来ならば、ここに全ての処理を書いても良いのです。けれど、それだとちょっとコード量が増えすぎてインデントも深くなってしまい、読みづらくなってしまうので、今回は「新着エントリーを表示する処理」は、以下のようにテンプレートファイルに切り分けました。(エディターでもこっちの方が読みやすい。)
<?php
//新着エントリー表示用の処理を書くところだけど
//コード量も多く、インデントが深くなり読みづらくなるので
//テンプレートファイル側に書く
get_template_part('new-entries'); ?>
ウィジェット作成クラス側で設定した変数を渡すには、グローバル変数を使って受け渡します。
新着エントリー表示用の処理をテンプレートで作る
ウィジェット追加するには基本的にfunctions.phpに書いていくのですが、コードの見やすさを考えて、新着エントリー表示に関する処理を、new-entries.phpというテンプレートファイルを作ってそこに書いていきます。
functions.phpに全て書いてしまった方が楽という人は、それでもいいと思います。
新着エントリーを表示する処理はこんな感じです。(new-entries.php)
<ul>
<?php global $g_entry_count; //グローバル変数の呼び出し?>
<?php query_posts('posts_per_page='.$g_entry_count); //クエリの作成?>
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<li class="new-entry">
<div class="new-entry-thumb">
<?php if ( has_post_thumbnail() ): // サムネイルを持っているときの処理 ?>
<a href="<?php the_permalink(); ?>" class="new-entry-image"><?php the_post_thumbnail( 'thumb100', array('style' => 'width:75px;height:75px;') ); ?></a>
<?php else: // サムネイルを持っていないときの処理 ?>
<a href="<?php the_permalink(); ?>" class="new-entry-image"><img src="<?php echo get_template_directory_uri(); ?>/images/no-image.png" alt="NO IMAGE" title="NO IMAGE" style="width:75px;height:75px;" /></a>
<?php endif; ?>
</div><!-- /.new-entry-thumb -->
<div class="new-entry-content">
<a href="<?php the_permalink(); ?>" class="new-entry-title"><?php the_title();?></a>
</div><!-- /.new-entry-content -->
</li><!-- /.new-entry -->
<?php endwhile;
else :
echo '<p>新着記事はありません。</p>';
endif; ?>
<?php wp_reset_query(); ?>
</ul>
<div class="clear"></div>
ここでのポイントは、functions.phpで設定したグローバル変数を呼び出していることです。
<?php global $g_entry_count; //グローバル変数の呼び出し?>
<?php query_posts('posts_per_page='.$g_entry_count); //クエリの作成?>
ちょっと作法的に良くないのかもしれません。けれど、Railsのようにテンプレートに変数を渡す方法を探したのですが、ちょっと調べた限りでは見つからなかったのでこういった方法にしました。
あとは、以下のように「thumb100」という100×100のサムネイルを無理やり75×75に変換しています。
<?php the_post_thumbnail( 'thumb100', array('style' => 'width:75px;height:75px;') ); ?>
「thumb100」の部分は、テーマで設定されているサムネイル設定に合わせて変更してください。75×75のサムネイルがあればそれが一番ですし、なければ近い大きさの物に編集してください。
テーマで使用しているサムネイル設定を知るにはfunctions.phpを「add_image_size」あたりで検索してみてください。
以下のようなものが見つかります。
add_image_size('thumb100',100,100,true);
設定方法などは長くなるので割愛。
スタイルシートの設定
あとはstyle.cssでスタイルを以下のように設定すればOKかと思います。
/************************************
** 新着エントリー
************************************/
#new-entries{
line-height:150%;
}
#new-entries h4{
margin-bottom:15px;
}
#new-entries ul {
padding-left:0;
}
#new-entries ul li {
clear: left;
float: none;
margin-bottom:10px;
}
#new-entries ul li img {
border: none;
display: inline;
float: left;
margin: 0 5px 10px 0;
}
動作確認
最後は動作確認です。
「外観→ウィジェット」でドラッグ&ドロップをして「新着エントリー」ウィジェットをサイドバーなどに移動します。
そして、「新着エントリー」ウィジェットの設定を以下のように設定しました。

タイトルを英語に変更して、表示数を少なめの3つにしています。
ブラウザで表示を確認すると以下のようになっています。

動作も問題ないようです。
まとめ
こういったことをやってみる前は、ウィジェットを作成するというから、もっと大変な作業なのかと思いました。
けれど、簡単なものならfunctions.phpにクラスを作って必要なところを変更するだけで、思ったより簡単に処理部分が作れてしまうというのは意外でした。(今回は2ヶ所に分けて書いたけど)
冒頭にも書きましたが、子テーマに追記するだけでもウィジェットが作れるようになるので、「テーマに独自のウィジェットを作成したい」なんて人は、是非試してみてください。
ウィジェットAPIの詳しい仕様については以下を参照してください。