見出し画像

【WordPress】プラグインなしでいいね機能を実装する(最終更新: 2024/01/20)

WordPressでカスタムフィールドを利用した、プラグインなしで「いいね」機能を実装するためのテーマ機能を公開します。


はじめに

このテーマ機能はプラグインではありません。
プラグインとして十分な機能は実装できたのではないかとは思っていますが、継続的なサポートは難しいと判断したのと、個人的に欲しいから作ったにすぎない、というのが実情です。
そのため、可能な限りのカスタマイズ方法の提供と、必要に応じた最低限のバージョンアップ(PHPのバージョンアップ等に伴う変更等)は行うつもりではありますが、実装自体はあくまで自己責任でお願いします。

ローカル開発環境はPHP7.4、ローカルテスト環境PHP8.2、本環境PHP8.1にて動作確認済みです。


1. 機能一覧

- 連続いいね機能
- 上限回数設定、及び制限時間の設定
-  ページ別集計機能(グラフ対応)
- 記事別に表示、非表示を指定できる機能(初期値は表示)
- ボタンテキスト、及び任意のアイコンフォントの指定
- 専用コード、ショートコードによる表示
- 引数による個別カスタマイズ
- サンクス画面(画像含む)

機能の多くはWordPressの標準機能を利用して実装しています。
データベースに独自のテーブルを追加する必要性のあるようなメッセージ送信機能、ブラックリスト機能、日別集計機能等は残念ながら提供していません。(これについては今後も実装する予定はありません)
機能最低限でありながら、可能な限り欲しい機能を持たせて作りました。

上限回数、制限時間に利用する一時キャッシュの保存には、WordPressの Transients API を使用。
グラフ機能は Google Charts のグラフライブラリを使用しています。

いいね集計画面

また、この「いいね」機能はカスタムフィールドを利用しているため、編集画面から各値を編集することが可能です。
テスト結果の上書き、及び他の同等機能からの乗り換えをお考えの方向けに、意図的に編集画面に専用セクションとして表示してあります。共同編集者が登録されている環境下では扱いにご注意ください。


2. ダウンロード

2-1. 設置に際しての注意事項

  • 設置、カスタマイズ、改造は自己責任でお願いします。

  • lib/custom_like.php に書かれた著作権・配布元表示は消さないでください。

  • 設置に際し、必ずバックアップを取るようにしてください。また、可能であればローカル環境でのテストを推奨しています。

  • 変数名等は可能な限り、他のプラグインとの競合が起きにくいように配慮致しましたが、万が一、不具合が起きたとしても作者は一切の責任を負いかねますので、予めご了承ください。

  • 素人が趣味で開発したものです。二次配布や販売についてはご遠慮ください。

2-2. 変更履歴

  • 2024/01/20 : ver2.00公開

  • 2023/03/27 : ver1.01(ポップアップ処理の修正)

  • 2023/03/26 : ver1.0公開

2-3. ダウンロードファイル

ver2.00のダウンロードはこちらからお願いします。


3. 基本設定

3-1. ファイル構成

ファイル構成は以下のとおりです。

フォルダ
   ├─ lib / custom_like.php
   ├─ js / ajax.js
   ├─ css / custom_like.css
   └─ img / thanks.png

以上のファイルをすべてお使いのテーマフォルダにアップロードしてください。
その上で functions.php に以下のコードを追加します。

<?php

locate_template('lib/custom_like.php', true); // いいね機能

以上でテーマ機能の読み込みは完了です。

3-2. 初期設定

このテーマ機能には可能な限りの汎用性を持たせるため、グローバル変数を利用した初期設定項目をご用意しました。
必要に応じて変更をお願いします。

lib/custom_like.php を開くと、9行目~15行目 に初期設定があります。
これはデフォルト値として使用されるものです。

/* -------------------- 初期設定 -------------------- */
// 変数を定義する
$GLOBALS['custom_like_text'] = 'いいね';         // ボタンテキスト
$GLOBALS['custom_like_icon'] = '<i class="fa fa-heart"></i>'; // 任意のアイコンフォント用htmlタグ
$GLOBALS['custom_like_img'] = 'img/thanks.png'; // サンクス画像
$GLOBALS['custom_like_limit'] = 10;              // 連続いいね上限
$GLOBALS['custom_like_reset'] = 24;              // 制限時間

上から順に、ボタンテキスト、アイコンフォントのHTMLタグ、サンクス画像用ファイル名、post_idごとの上限回数、時間制限に用いるキャッシュの保存期間を設定することができます。
また、アイコンフォントは既に導入済みの環境に合わせてご自由に設定できるように致しました。
これは自分が Font Awesome を利用していないため、アイコンフォントを利用するような機能やプログラムではよく書き換えを余儀なくされることから対応しました。
導入済みの環境、またはお使いになりたいアイコンのHTMLタグに置き換えてご利用ください。

3-3. テンプレートファイルへの追加

テンプレートファイルへの追加は自動では行われません。
そのため、以下のコードをループ内に設置してください。

<?php custom_like_button(); ?>

また、この「いいね」機能はショートコードにも対応しています。
記事内にて任意の場所に設置する場合は、こちらのコードをご利用ください。

[custom_like]

このテーマ機能を追加すると、各編集画面に専用のセクションが追加されます。
セクションには「いいね」の回数を保存するためのフォームと、表示/非表示を選択するためのチェックボックスがありますが、チェックボックスはデフォルトで初期値としてチェックが入っています。

編集画面

そのため、関数をテンプレートに追加することによって一律にいいねボタンが表示されるようになりますので、既存環境に追加の際はご注意ください。
表示/非表示のための条件分岐はデフォルトで設定済みです。
新たに条件分岐を追加する必要はないので、各編集画面から必要に応じて切り替えを行ってください。


4. CSS

4-1. ボタン用CSS

この「いいね」機能のボタンには必要最低限のCSSのみが設定されています。
以下は装飾に必要な各classの一覧です。

.custom_like-btn           // ボタン用
.custom_like-liked         // ボタンを押した後のスタイル
.custom_like-btn:disabled  // 上限値に達した際にボタンを無効化するためのスタイル

例えばテンプレートや投稿タイプごとにスタイルを切り替えたい場合、大抵のテーマには <body> に固有のid、またはclassが振られていると思います。
それを利用して、以下のように独自のCSSをカスタムCSS、及び自作CSSなどに追加してみてください。

[id^='post-'] .custom_like-btn {}
[id^='post-'] .custom_like-liked {}

自作テーマの場合は予め固有のid、classを追加しておくことでより、テーマ全体のカスタマイズがしやすくなると思います。

なお、以下のCSSについてはボタンテキストを上下中央に揃えるためのものですので、必要がない限りはそのままにしてください。

.custom_like-btn {
  line-height: normal;
}

.custom_like-btn::before {
  content: '';
  display: inline-block;
  height: 1em;
  vertical-align: middle;
}

4-2. サンクス画面用CSS

サンクス画面は以下のclassで指定しています。

.custom_like-popup {
  color: #555;
  font-size: .875rem;
  background:#fff;
  text-align: left;
  border: 1px solid #dcdddd;
  border-radius: 5px;
  width: 400px;
  box-shadow: 0 5px 8px 0 rgba(220, 221, 221, 0.5);
}

borderbackground 、フォント周りなどは環境に合わせて好きなように変更していただければと思います。
ただし、「変更不可」と書かれた以下の部分はポップアップ表示に関するレイアウト部分になります。
可能な限り、いじらないようにお願いします。

/* 変更不可 */
.custom_like-popup {
  position: absolute;
  padding: 10px;
  margin: 10px auto;
  max-width: 100%;
  left: 50%;
  transform: translateX(-50%);
  z-index: 9999;
  transition: all .4s ease-out;
  visibility: hidden;
  opacity: 0;
}
.custom_like-popup.show {
  visibility: visible;
  opacity: 1;
}

/* 左寄せ */
.custom_like-wrap--left {
  text-align: left;
}
.custom_like-wrap--left > .custom_like-popup {
  left: 0;
  transform: translateX(50%);
}

/* 右寄せ */
.custom_like-wrap--right {
  text-align: right;
}
.custom_like-wrap--right > .custom_like-popup {
  right: 0;
  transform: translateX(-25%);
}

@media screen and (max-width:767.98px) {
  .custom_like-popup,
  .custom_like-wrap--left > .custom_like-popup,
  .custom_like-wrap--right > .custom_like-popup {
    left: 50%;
    transform: translateX(-50%);
    bottom: auto;
    right: auto;
    margin: 10px auto;
  }
}

画像については img/thanks.png を差し替えることで任意の画像を表示することができます。
JPEG画像等を使用する場合は、初期設定からファイル名、及び拡張子を変更してください。
画像サイズについては特に指定はありませんが、同梱しているサンプル画像は 640*480px でご用意させていただきました。あくまでサンプル用なので、ご自身でお好きな画像をご用意ください。
「お礼画像」等のキーワードで検索すると、フリーの素材も多く出てくると思いますので、よろしければ探してみてください。


5. カスタマイズ

5-1. ボタンカスタマイズ

ボタンのデサインは lib/custom_like.php 内で指定しますが、テンプレート、あるいは投稿タイプごとに表示方法を分けたいというような場合があると思います。
そのため、引数を利用できるようにしてみました。

custom_like_button($post_id, $custom_like_icon, $custom_like_text)
  • $post_id:投稿IDを指定。個別指定も可。

  • $custom_like_icon:アイコンフォントの指定。

  • $custom_like_text:ボタンテキストを指定。

例えば、アイコンフォントとカウントだけを表示したい場合は以下のように書きます。

<?php custom_like_button(get_the_ID(),'<i class="fas fa-favorite"></i>', ''); ?>

あるいは、$post_id に任意のidを指定することで、該当する投稿のいいねボタンを呼び出すこともできます。

<?php custom_like_button(1,'<i class="fas fa-favorite"></i>', 'テキスト'); ?>

ショートコードの場合も同じです。
こちらは記事内で設置するので、$post_id を省略することも可能です。

[custom_like custom_like_icon='<i class="fas fa-favorite"></i>' custom_like_text='Like']

HTMLタグを含んでいるので、引数はシングルクォーテーションで括ってください。

5-2. カウントを非表示にする

カウントの非表示については、デフォルトでは提供していません。
そのため、CSSで対応することになります。

.custom_like-count {
  display: none;
}

これでカウンターは非表示になります。

5-3. 集計ページの追加

これはカスタム投稿タイプ用に集計ページを分けたい、あるいは追加したいという方向けのカスタマイズです。

初期設定では「いいね」が0以上の全ての投稿タイプが集計ページで表示されるようになっています。
しかし、カスタム投稿タイプの運用方法次第では別々に分けたい、という方がいらっしゃると思います。
というよりも、自分がそのタイプだったためにこの機能を残しました。

lib/custom_like.php にはコメントアウトした固定ページ用と、カスタム投稿タイプ用の集計ページのフォーマットを残してあります。
しかし、コードが長くなってしまうため、ページの中身ついては省略してありますので、コピー&ペーストで使い回しをします。
コピーするコードは lib/custom_like.php の 255~324行目 になります。
実際のコードは以下のとおりです。

   ?>
  <div class="wrap">
    <h1>いいね(集計)</h1>
    <table class="widefat">
      <thead>
        <tr>
          <th>タイトル</th>
          <th>いいね数</th>
          <th>グラフ</th>
        </tr>
      </thead>
      <tbody>
        <?php
        if ( $query->have_posts() ) {
          while ( $query->have_posts() ) {
            $query->the_post();
            $custom_like = get_post_meta( get_the_ID(), 'custom_like', true );
            ?>
            <tr>
              <td><?php the_title(); ?></td>
              <td><?php echo $custom_like; ?></td>
              <td style="width:auto" id="chart_<?php echo get_the_ID(); ?>">
                <script>
                  google.charts.load('current', {'packages':['corechart']});
                  google.charts.setOnLoadCallback(drawChart<?php echo get_the_ID(); ?>);
                  function drawChart<?php echo get_the_ID(); ?>() {
                    var data = google.visualization.arrayToDataTable([
                      ['', 'いいね数'],
                      ['', <?php echo $custom_like; ?>]
                    ]);
                    var options = {
                      width: 700,
                      height: 30,
                      legend: {position: 'none'},
                      bars: 'horizontal',
                      chartArea: { width: '100%', },
                      bar: { groupWidth: '2px' },
                      hAxis: {
                        maxValue: 100,
                        minValue: 0
                      },
                      axes: {
                        x: {0: {side: 'top', label: 'いいね数'}}
                      },
                      colors: ['#8491c3'], // グラフの色を指定する
                    };
                    window.onresize = function(){
                      drawChart();
                    }
                    var chart = new google.visualization.BarChart(document.getElementById('chart_<?php echo get_the_ID(); ?>'));
                    chart.draw(data, options);
                  }
                </script>
              </td>
            </tr>
            <?php
          }
        } else {
          ?>
          <tr>
            <td colspan="2">No pages found.</td>
          </tr>
          <?php
        }
        wp_reset_postdata();
        ?>
      </tbody>
    </table>
  </div>
  <?php

必ず、255行目?> と、324行目<?php を忘れないようにしてください。

次に、そのすぐ下に、固定ページ用のメニューコードと、カスタム投稿タイプ用のメニューコードがあります。

// いいね集計(固定ページ)を表示させる関数
function custom_submenu1_page() {
  echo '<head><script src="https://www.gstatic.com/charts/loader.js"></script></head>';

  // WP_Queryを使って、投稿を取得
  $query_args = array(
    'post_type'      => 'page',
    'posts_per_page' => -1,
    'meta_query'     => array(
      array(
        'key'     => 'custom_like',
        'value'   => 0,
        'compare' => '>',
        'type'    => 'NUMERIC',
      ),
    ),
    'orderby'        => 'ID',
    'order'          => 'ASC',
  );
  $query = new WP_Query( $query_args );

// ここにコピーしたコードを貼り付けてください

}
// いいね集計(カスタム投稿タイプ)を表示させる関数
function custom_submenu2_page() {
  echo '<head><script src="https://www.gstatic.com/charts/loader.js"></script></head>';

  // WP_Queryを使って、投稿を取得
  $query_args = array(
    'post_type'      => 'novels',
    'posts_per_page' => -1,
    'meta_query'     => array(
      array(
        'key'     => 'custom_like',
        'value'   => 0,
        'compare' => '>',
        'type'    => 'NUMERIC',
      ),
    ),
    'orderby'        => 'ID',
    'order'          => 'ASC',
  );
  $query = new WP_Query( $query_args );
// ここにコピーしたコードを貼り付けてください
}

ここに記載したコードはわかりやすくするためにコメントアウトしていませんが、実際のファイルはこれらの部分がコメントアウトされています。
一括置換がしやすいように「//*」という形でコメントアウトしてあるので、各エディタで置換対象に「//*」を入れて空白置換で置き換えます。
コメントアウトを外した後、「ここにコピーしたコードを貼り付けてください」という部分に custom_like_menu_page() からコピーしたコードを貼り付けます。
更にもう1行、 custom_like_menu_page() の 240行目 にもコメントアウトされた行があります。

    'post_type'      => 'any',
    // 'post_type'      => 'post',

初期メニューを投稿専用にするには、このコメントアウトを外し、'post_type' => 'post', を有効化してください。
代わりに 'post_type' => 'any', をコメントアウトするか削除します。
これにより、集計画面はそれぞれ投稿、固定ページ、指定したカスタム投稿タイプに分けることができるようになります。
固定ページで集計する必要のない方は、'post_type' => 'page', をカスタム投稿タイプ名に変えてもご利用いただけます。
また、ページタイトル等も環境に合わせてご自由に変更してください。

カスタム投稿タイプの集計画面

更に追加したい場合は、227行目 にまず、以下のコードを追加します。

  // サブメニュー3を追加
  add_submenu_page(
    'custom-like-menu', // 親メニューのスラッグ
    'いいね | カスタム投稿タイプ(集計)', // ページのタイトルタグ
    'カスタム投稿タイプ(集計)', // メニューに表示される名前
    'manage_options', // 権限
    'custom-submenu3', // メニューのスラッグ
    'custom_submenu3_page' // メニューの中身を表示させる関数の名前
  );

そして今度はサブメニューのコードをまるっとコピーして一番最後に追加してください。
また、その際に関数名のナンバリングを間違えないようにしてください。

5-4. サンクス画面の表示示位置

サンクス画面はポップアップで表示されます。
表示時間はデフォルトでは5秒です。
これは js/ajax.js の冒頭、4行目 で設定することができます。

  // お礼メッセージを表示する時間(単位はミリ秒 / 5000=5秒)
  var thanksMsgTime = 5000;

表示位置は特定の親要素を持たない場合、ボタンの位置に関係なく画面中央に表示されるように指定してあります。
しかし、ボタンの表示位置に伴い、特定の親要素を指定することでサンクス画面の位置も変えられるように専用のclassをご用意しました。
必要に応じてご利用ください。

テンプレートに以下のように記述します。

<!-- 左寄せ -->
<div class="custom_like-wrap--left">
  <?php custom_like_button(); ?>
</div>
<!-- 右寄せ -->
<div class="custom_like-wrap--right">
  <?php custom_like_button(); ?>
</div>
左寄せ配置
右寄せ配置

なお、スマートフォン環境下(max-width:767.98px)では一律、サンクス画面は画面中央に表示されるようにしてあります。

5-5. サンクス画面を上限時にのみ表示する

サンクス画面は連続いいねの場合、初回の一回目のみに表示されます。
しかし、通常は表示させず、上限回数時にのみ、表示させたいという方がいらっしゃるかもしれません。
そういう方のために、このやり方についても一応、書き残しておこうと思います。

js/ajax.js の 37行目~45行目 に以下のコードがあります。

// HTMLポップアップに「show」クラスを追加
$target.next('.custom_like-popup').addClass('show');

setTimeout(function() {
  $target.next('.custom_like-popup').removeClass('show');
  setTimeout(function() {
    $target.next('.custom_like-popup').remove();
  }, 300);
}, thanksMsgTime);

このコードを切り取り、32行目 の } else { の前に挿入してください。
また、30行目 にある以下のコードをコメントアウトするか、削除します。

alert('このページでの「いいね」は本日の上限に達しました。');

次に、lib/custom_like.php を開き、30行目にある以下のコードを編集します。

echo '<div class="custom_like-popup"><img src="' . get_template_directory_uri() . '/'. $GLOBALS['custom_like_img'] .'" width="100%" height="100%"><br>'. "\n" .'いいねありがとうございます!</div>';

jQuery側のアラートを削除していますので、ポップアップの中で上限回数に達したことを通知する旨を追記します。

  echo '<div class="custom_like-popup"><img src="' . get_template_directory_uri() . '/'. $GLOBALS['custom_like_img'] .'" width="100%" height="100%"><br>'. "\n" .'いいねありがとうございます!<br>' . "\n" .'このページでの「いいね」は本日の上限に達しました。</div>';

また、もし一日の上限回数を1回限定にしたい方も、同様に js/ajax.js のアラートを非表示にするなどのカスタマイズをされたほうがいいかもしれません。

5-6. メールフォームと組み合わせる

このテーマ機能にはメッセージを送信するような機能は備わっていません。
そのため、所謂Web拍手のように使うためには、メールフォームプラグインなどと組み合わせ、併用する必要性があります。
ただし、基本的にはメールフォームを開くためのスイッチは、いいねボタンとは切り離して運用するべきだと考えています。
ですがもし、いいねボタンを押したらフォームが開くようにしたい方は、以下のようにしてみてください。

  <?php custom_like_button(); ?>
  <div class="form--block">
    <!-- フォーム用のコード -->
  </div>
.form--block {
  transition: all .4s;
}

.form--block {
  max-height: 0;
  opacity: 0;
  visibility: hidden;
}

.form--block.show {
  opacity: 1;
  visibility: visible;
  max-height: 100vh;
}
success: function(response) {
  if (response === 'customLikeLimit') {
    alert('このページでの「いいね」は本日の上限に達しました。');
    $target.prop('disabled', true); // クリックされた要素のみ無効化する
  } else {
    $target.find('.custom_like-count').html(count);
    $target.addClass('custom_like--liked');
    localStorage.setItem('customLikeStyle_' + postID, 'liked');

    // HTMLポップアップに「show」クラスを追加
    $target.next('.custom_like-popup').addClass('show');

    setTimeout(function() {
      $target.next('.custom_like-popup').removeClass('show');
      setTimeout(function() {
        $target.next('.custom_like-popup').remove();
      }, 300);
    }, thanksMsgTime);

  $('.form--block').addClass('show');  // ここを追加
  }
}

jQueryを使用してボタンをクリック時に、フォームを囲った .form--block にclassを追加します。
これにより、メールフォームが開くようになります。
あるいは、上限回数に達したときにフォームを開くようにしてもいいかもしれません。
ただし、フォームとの併用はあくまで固定ページ、個別作品ページ等でのご利用に留めることをお勧め致します。


6. キャッシュプラグインをご利用の方へ

このテーマ機能を導入するにあたって、WP Super Cache 等をご利用の方は注意してください。
いいねボタンを押した際にカスタムフィールドへの保存はされますが、キャッシュが残っていると、フロントエンドではカウントが正しく表示されないことがあります。
管理画面での値とフロントエンドでの表示に誤差がある場合は、一度キャッシュの確認をお願いします。
なお、本テーマ機能を導入後にデータベースの最適化を行うと、Transients APIに保存されたキャッシュもクリアされることになります。その点についてのご留意ください。

この記事が気に入ったらサポートをしてみませんか?