Wordpress

WordPressの自作テーマでサイドバーウィジットにお気に入り記事一覧を作る

こんにちは、シロウです。

今回の記事では『サイドバーウィジットにお気に入り記事一覧を作成する方法』を紹介していきます。

完成イメージは下記の通りです。

なぜかわかりませんが、ウィジット に独自のカスタム項目を追加する方法を解説してくれている記事が少なくてかなり苦労しました(-_-;)

たぶん、完成までに6時間ぐらいかかった思いますが、この記事を見ている人は30分もかからずに出来ると思います。笑

ということで、早速ですが見ていきましょう。

*結構長いので、とりあえず実装したい!って方は最後のまとめでfunctions.phpに記述する全コードをまとめているので、そっちをコピペしてくれれば出来るかと。

これから実装する機能

念のためにこれから実装する機能を解説しておきます。

  • ウィジットに新しい項目として『お気に入り記事一覧』を作成する
  • 記事の編集画面から各記事をお気に入り記事に指定できる
  • 記事の編集画面でお気に入りに指定した記事をサイドバーで出力する

とこんな感じの機能を今回は作ってみました。

サイドバーにお気に入り記事一覧を作る手順

手順は下記の通りです。

  • サイドバーウィジットを作成する
  • ウィジットに『お気に入り記事』の項目を作成する
  • 記事編集画面(エディタ)のカスタムフィールドにお気に入りに設定するjin_icon_check size=”20px”boxを作る

たったこれだけです。簡単ですので、どんどん作っていきましょう。

①サイドバーウィジットを作成する

まずはサイドバーウィジットを作成するために下記のコードをfunctions.phpに記述してください。

/**
 * ウィジェットエリアを定義します。
 */
    function bj_register_sidebars()
    {
        register_sidebar(array(
            'id'            => 'primary-widget-area',
            'name'          => 'サイドバー',
            'description'   => 'サイドバーに表示されるウィジェットエリアです。',
            'before_widget' => '<section id="%1$s" class="widget %2$s">',
            'after_widget'  => '</section>',
            'before_title'  => '<h4 class="widget-title">',
            'after_title'   => '</h4>',
        ));
    }

    add_action('widgets_init', 'bj_register_sidebars');

これで下記のようなサイドバーウィジットが作成されたはずです。

これは調べればいくらでも出てくると思うので説明は割愛します。『wordpress サイドバー ウィジット追加』とかで調べてみてくださいm(_ _)m

ウィジットに『お気に入り記事』を作る

ちょっと長いし、嫌になるかもしれませんが、理解せずともとりあえず下記コードをコピペでfunctions.phpに貼り付ければウィジットに項目が追加されるはずです。

class My_Widget extends WP_Widget
{
    //コンストラクタ
    //自作ウィジェットを登録する(ここはコピペでOK)
    public function __construct()
    {
        parent::__construct(
            false,
            $name = 'オススメ記事',
            array( 'description' => 'サイドバーに表示する記事を設定', )
        );
    }

    //管理画面の表示用コードを書く
    public function form($instance)
    {
        ?> 
<p>
    <label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Title:'); ?></label>
    <input type="text" class="widefat"
        id="<?php echo $this->get_field_id('title'); ?>"
        name="<?php echo $this->get_field_name('title'); ?>"
        value="<?php echo esc_attr($instance['title']); ?>">
</p>
<p>
    <label for="<?php echo $this->get_field_id('limit'); ?>"><?php _e('表示する投稿数:'); ?></label>
    <input type="text"
        id="<?php echo $this->get_field_id('limit'); ?>"
        name="<?php echo $this->get_field_name('limit'); ?>"
        value="<?php echo esc_attr($instance['limit']); ?>"
        size="3">
</p>
<?php
    }

    //管理画面で設定を変更した時の処理を書く
    //これがないと変更が保存されない
    //変更前の値は$old_instance、変更後の値は$new_instanceに入っている
   //$old_instanceには上記で設定したtitleとかlimitが連想配列で入っている(と思う)、
    public function update($new_instance, $old_instance)
    {
        $instance = $old_instance; 
        $instance['title'] = strip_tags($new_instance['title']);
        $instance['limit'] = is_numeric($new_instance['limit']) ? $new_instance['limit'] : 5;
        return $instance;
    }

    // ウィジェットを配置した時の表示用コード
    public function widget($args, $instance)
    {
        //とりあえず↓これがいるっぽい
        extract($args);
 
       //titleが空だった時の処理(よくわからん人はコピペでOK)
        if ($instance['title'] != '') {
            $title = apply_filters('widget_title', $instance['title']);
        }
       //$before_widgetとかは『①サイドバーウィジットを作成する』で書いたコードのやつが入っている
        echo $before_widget;
        if ($title) {
            echo $before_title . $title . $after_title;
        } ?>
<ul class="recommend-post">
    <?php
        $args = array(
        'posts_per_page' => $instance['limit'],
        'meta_query' => array(
            array('key'=>'recommend_post', 'value'=>'1', 'compare'=>'=')
        ),
        );

        query_posts($args);
        if (have_posts()):
        while (have_posts()): the_post(); ?>
    <li>
        <?php if (has_post_thumbnail()): ?>
        <a href="<?php the_permalink(); ?>"><?php the_post_thumbnail(array(400,400)); ?></a>
        <?php else: ?>
        <a href="<?php the_permalink(); ?>"><img
                src="<?php bloginfo('template_url'); ?>/images/no-image.jpg"
                alt=""></a>
        <?php endif; ?>
        <div>
            <h5><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h5>
        </div>
    </li>
    <?php endwhile;
        endif; ?>
</ul>
<?php
    echo $after_widget;
    }
}

//自作ウィジェットを使えるようにする処理
register_widget('My_Widget');

一応コメントで説明しているつもりですが、もう少し詳しく解説しておきます。

コードの解説

    //コンストラクタ
    //自作ウィジェットを登録する(ここはコピペでOK)
    public function __construct()
    {
        parent::__construct(
            false,
            $name = 'オススメ記事',
            array( 'description' => 'サイドバーに表示する記事を設定', )
        );
    }

とりあえず上記はコピペでOKです。

名前を変更したかったら$nameを好きな文字に変えてください。

//管理画面の表示用コードを書く
    public function form($instance)
    {
        ?> 
<p>
    <label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Title:'); ?></label>
    <input type="text" class="widefat"
        id="<?php echo $this->get_field_id('title'); ?>"
        name="<?php echo $this->get_field_name('title'); ?>"
        value="<?php echo esc_attr($instance['title']); ?>">
</p>
<p>
    <label for="<?php echo $this->get_field_id('limit'); ?>"><?php _e('表示する投稿数:'); ?></label>
    <input type="text"
        id="<?php echo $this->get_field_id('limit'); ?>"
        name="<?php echo $this->get_field_name('limit'); ?>"
        value="<?php echo esc_attr($instance['limit']); ?>"
        size="3">
</p>
<?php
    }

上記のコードについてもコピペで実装は可能ですが、解説しておきます。
formメソッドはウィジットの設定画面で表示されるフィールドとかを設定する項目です。
ここにinput要素とかを使うことによって、設定画面でタイトルとか表示する記事数をいじることができます。
$this→get_field_id系の記述が多いですがこれはWordpress側がウィジットに項目を作成する時はこの関数を使ってね、と用意してくれているやつなので、この引数に設定したい値を書けばOKです。

注意 : フォーム要素の名前と ID を生成するには get_field_name() および get_field_id() 関数を使用する必要があります。

_e()についてはよくわかりませんが(というか理解しようとしていないだけですが)、「こちらの記事」とかわかりやすそうなので、理解したい方は(*・ω・)ノ

//管理画面で設定を変更した時の処理を書く
    //これがないと変更が保存されない
    //変更前の値は$old_instance、変更後の値は$new_instanceに入っている
   //$old_instanceには上記で設定したtitleとかlimitが連想配列で入っている(と思う)、
    public function update($new_instance, $old_instance)
    {
        $instance = $old_instance; 
        $instance['title'] = strip_tags($new_instance['title']);
        $instance['limit'] = is_numeric($new_instance['limit']) ? $new_instance['limit'] : 5;
        return $instance;
    }

上記のコードはウィジット の設定画面で名前とかを変更した時に保存する処理です。updateメソッドを使います。
正直ここは僕も特に調べず適当にやったのであまりわかりませんが、要は$new_instanceの中に連想配列として、さっきのformメソッド内で記述したinputのnameの文字列が入っているのでそっちに合わしてあげればいいだけですね。

    // ウィジェットを配置した時の表示用コード
    public function widget($args, $instance)
    {
        //とりあえず↓これがいるっぽい
        extract($args);
 
       //titleが空だった時の処理(よくわからん人はコピペでOK)
        if ($instance['title'] != '') {
            $title = apply_filters('widget_title', $instance['title']);
        }
       //$before_widgetとかは『①サイドバーウィジットを作成する』で書いたコードのやつが入っている
        echo $before_widget;
        if ($title) {
            echo $before_title . $title . $after_title;
        } ?>
<ul class="recommend-post">
    <?php
        $args = array(
        'posts_per_page' => $instance['limit'],
        'meta_query' => array(
            array('key'=>'recommend_post', 'value'=>'1', 'compare'=>'=')
        ),
        );

        query_posts($args);
        if (have_posts()):
        while (have_posts()): the_post(); ?>
    <li>
        <?php if (has_post_thumbnail()): ?>
        <a href="<?php the_permalink(); ?>"><?php the_post_thumbnail(array(400,400)); ?></a>
        <?php else: ?>
        <a href="<?php the_permalink(); ?>"><img
                src="<?php bloginfo('template_url'); ?>/images/no-image.jpg"
                alt=""></a>
        <?php endif; ?>
        <div>
            <h5><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h5>
        </div>
    </li>
    <?php endwhile;
        endif; ?>
</ul>
<?php
    echo $after_widget;
    }
}

上記のコードでウィジットを設置した時に出力されるHTMLを記述しています。
ぶっちゃけ僕もあまり理解していませんが、とりあえずextract($args);こいつがいるっぽいので最初に書いておきます。
あとは$instanceの連想配列にウィジットの設定画面で記入した値が入っているので表示したいならそれを使って色々しています。これもinputのname属性で記述した文字列と合わせれば、そのname属性の値が得られるので簡単ですね。
あと$before_widgetとかは①で『’before_widget’ => ‘<section id=”%1$s” class=”widget %2$s”>’,』とかしたやつのことです。

③カスタムフィールドにお気に入りに設定するjin_icon_check size=”20px”boxを作る

カスタムフィールドエリアを作るには下記をコピペすればOKです。
(他の処理も記述していたのですが、オススメ記事用だけを抜き出しているため、関数名がちょっと変ですが気にしないでください笑)

また、カスタムフィールドについてはいろんな記事が調べれば出てくると思うので、解説は割愛します。(ただ疲れただけですが、、、笑)

// カスタムフィールドの入力エリア
function seo_custom_fields()
{
    global $post;
    $recommend_post = get_post_meta($post->ID, 'recommend_post', true);
    if ($recommend_post==1) {
        $recommend_post="jin_icon_check size="20px"ed";
    } else {
        $recommend_post= "/";
    }
    echo '<p>おすすめ記事<br>';
    echo '<input type="jin_icon_check size="20px"box" name="recommend_post" value="1"' . $recommend_post . '> </p>';
}
 
function save_seo_custom_fields($post_id)
{
    if (!empty($_POST['recommend_post'])) {
        update_post_meta($post_id, 'recommend_post', $_POST['recommend_post']);
    } else {
        delete_post_meta($post_id, 'recommend_post');
    }
}
add_action('admin_menu', 'add_seo_custom_fields');
add_action('save_post', 'save_seo_custom_fields');

CSSでスタイルを整える

最後にCSSでスタイルを調整すれば完成です。

/* ウィジット共通 */
.widget {
    background-color: #fff;
    margin-bottom: 30px;
    border: 1px solid #7b7b7b21;
    border: 0.1px solid rgba(75, 75, 75, 0.2);
}

.widget h4 {
    color: #7b7b7b;
    font-size: 23px;
    position: relative;
    margin-bottom: 30px;
    padding-top: 30px;
    text-align: center;
    transition: 0.6s;
    -webkit-transition: all 0.6s;
    -moz-transition: all 0.6s;
    -o-transition: all 0.6s;
}

/* オススメ記事 */
.recommend-post {
    list-style: none;
}

.recommend-post li {
    text-align: center;
    margin-top: 20px;
    border-bottom: 1px dashed #7b7b7ba4;
}

.recommend-post li:last-child {
    border: none;
}

.recommend-post img {
    width: 95%;
    height: 100%;
    display: block;
    margin: 0 auto;
}

.recommend-post p {
    margin: 10px 0 0 0;
}

.recommend-post h5 {
    font-size: 16px;
    padding: 20px 5px 0;
    text-align: center;
}

まとめ:全処理を1つにまとめました

とりあえず早く実装したいって方は下記コードをfunctions.phpに丸っとコピペしてください。(CSSは上記のやつを使ってください。)

/**
 * ウィジェットエリアを定義します。
 */
    function bj_register_sidebars()
    {
        register_sidebar(array(
            'id'            => 'primary-widget-area',
            'name'          => 'サイドバー',
            'description'   => 'サイドバーに表示されるウィジェットエリアです。',
            'before_widget' => '<section id="%1$s" class="widget %2$s">',
            'after_widget'  => '</section>',
            'before_title'  => '<h4 class="widget-title">',
            'after_title'   => '</h4>',
        ));
    }

add_action('widgets_init', 'bj_register_sidebars');


class My_Widget extends WP_Widget
{
    //コンストラクタ
    //自作ウィジェットを登録する(ここはコピペでOK)
    public function __construct()
    {
        parent::__construct(
            false,
            $name = 'オススメ記事',
            array( 'description' => 'サイドバーに表示する記事を設定', )
        );
    }

    //管理画面の表示用コードを書く
    public function form($instance)
    {
        ?> 
<p>
    <label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Title:'); ?></label>
    <input type="text" class="widefat"
        id="<?php echo $this->get_field_id('title'); ?>"
        name="<?php echo $this->get_field_name('title'); ?>"
        value="<?php echo esc_attr($instance['title']); ?>">
</p>
<p>
    <label for="<?php echo $this->get_field_id('limit'); ?>"><?php _e('表示する投稿数:'); ?></label>
    <input type="text"
        id="<?php echo $this->get_field_id('limit'); ?>"
        name="<?php echo $this->get_field_name('limit'); ?>"
        value="<?php echo esc_attr($instance['limit']); ?>"
        size="3">
</p>
<?php
    }

    //管理画面で設定を変更した時の処理を書く
    //これがないと変更が保存されない
    //変更前の値は$old_instance、変更後の値は$new_instanceに入っている
   //$old_instanceには上記で設定したtitleとかlimitが連想配列で入っている(と思う)、
    public function update($new_instance, $old_instance)
    {
        $instance = $old_instance; 
        $instance['title'] = strip_tags($new_instance['title']);
        $instance['limit'] = is_numeric($new_instance['limit']) ? $new_instance['limit'] : 5;
        return $instance;
    }

    // ウィジェットを配置した時の表示用コード
    public function widget($args, $instance)
    {
        //とりあえず↓これがいるっぽい
        extract($args);
 
       //titleが空だった時の処理(よくわからん人はコピペでOK)
        if ($instance['title'] != '') {
            $title = apply_filters('widget_title', $instance['title']);
        }
       //$before_widgetとかは『①サイドバーウィジットを作成する』で書いたコードのやつが入っている
        echo $before_widget;
        if ($title) {
            echo $before_title . $title . $after_title;
        } ?>
<ul class="recommend-post">
    <?php
        $args = array(
        'posts_per_page' => $instance['limit'],
        'meta_query' => array(
            array('key'=>'recommend_post', 'value'=>'1', 'compare'=>'=')
        ),
        );

        query_posts($args);
        if (have_posts()):
        while (have_posts()): the_post(); ?>
    <li>
        <?php if (has_post_thumbnail()): ?>
        <a href="<?php the_permalink(); ?>"><?php the_post_thumbnail(array(400,400)); ?></a>
        <?php else: ?>
        <a href="<?php the_permalink(); ?>"><img
                src="<?php bloginfo('template_url'); ?>/images/no-image.jpg"
                alt=""></a>
        <?php endif; ?>
        <div>
            <h5><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h5>
        </div>
    </li>
    <?php endwhile;
        endif; ?>
</ul>
<?php
    echo $after_widget;
    }
}

//自作ウィジェットを使えるようにする処理
register_widget('My_Widget');


// カスタムフィールドの入力エリア
function seo_custom_fields()
{
    global $post;
    $recommend_post = get_post_meta($post->ID, 'recommend_post', true);
    if ($recommend_post==1) {
        $recommend_post="jin_icon_check size="20px"ed";
    } else {
        $recommend_post= "/";
    }
    echo '<p>おすすめ記事<br>';
    echo '<input type="jin_icon_check size="20px"box" name="recommend_post" value="1"' . $recommend_post . '> </p>';
}
 
function save_seo_custom_fields($post_id)
{
    if (!empty($_POST['recommend_post'])) {
        update_post_meta($post_id, 'recommend_post', $_POST['recommend_post']);
    } else {
        delete_post_meta($post_id, 'recommend_post');
    }
}
add_action('admin_menu', 'add_seo_custom_fields');
add_action('save_post', 'save_seo_custom_fields');

ちょっと今回の記事は長すぎました、すいません。笑

次からはもっと短くわかりやすく解説出来るように頑張りますm(_ _)m

それではまた(*´ω`*)ノ