【徹底解説】WooCommerceのレビュー機能をカスタマイズする方法

ネットショップにおいてレビュー機能は非常に重要です。

楽天やアマゾンなどの大手通販サイトでも、他の人の口コミを参考にして商品を購入する方は多いと思います。

WordPressでネットショップを作れるWooCommerceには、標準でレビュー機能があります。

しかし、以下のように使いにくい点もあります。

  • アバターの変更が大変
  • 初期状態ではレビューに本名が表示される
  • 一つの商品に同じ人が何度もレビューできる
  • レビューの件数が多いときのページャーの表示順序に違和感がある

この記事では、WooCommerceのレビュー機能を使いやすく改善する方法を紹介します。

なお、Storefrontというテーマでデモサイトを作っています。使用しているテーマやWordPressの設定などによっては、記事の内容と異なる可能性があります。

WooCommerceのカスタマイズに関しては、以下の記事も参考にしてください。

目次

作成するレビュー機能のイメージ

この記事では、以下のようなレビュー機能を商品ページに作成します。

WooCommerceのレビュー機能のサンプル

主な特徴は以下の通りです。

  • レビューにアバターを表示して、マイページから変更できる
  • 購入者が匿名でもレビューできる
  • 一つの商品に同じ人が一度しかレビューできない
  • ページャーを設置して、最新のレビューから順番に表示する

なお、レビュー機能を作成したら、必ずテストを行いましょう。

WooCommerceのアカウントとプライバシーの設定

WooCommerceのネットショップでアカウントを作成するには、管理画面の「WooCommerce」⇒「設定」⇒「アカウントとプライバシー」から「アカウント作成」の設定を行います。

実際にネットショップで商品の購入を行い、そのアカウントでレビューができるかテストをしてみてください。

WooCommerceのレビューを有効にする

WooCommerceのレビューを有効化

WooCommerceでレビューを有効化するには、商品の編集ページを開き、商品データーの上級者向けタブから「レビューを有効化」にチェックを入れます。

WooCommerceのレビューに関するディスカッションの設定

また、WooCommerceのレビューはWordPressのコメントを使っているため、管理画面の「設定」⇒「ディスカッション」の設定が影響します。

重要だと思う設定を補足します。

  • 新しい投稿へのコメントを許可
    チェックを入れると、商品の編集ページの「レビューを有効化」に初期状態でチェックが入る
  • ユーザー登録してログインしたユーザーのみコメントをつけられるようにする
    チェックを入れると、ログインしないとレビューができない
  • コメントの手動承認を必須にする
    チェックを入れると、管理画面から承認しないとレビューが公開されない。なお、承認は管理画面の「コメント」か商品の編集ページからできる。

マイページからアバターを変更する

WooCommerceのレビューでアバターを表示または非表示にするには、管理画面の「設定」⇒「ディスカッション」にある「アバターを表示する」を設定します。

WooCommerceのレビューにアバターを表示する

標準ではGravatar(グラバター)というアバター作成サービスに登録しているものが表示されます。

しかし、ネットショップの購入者がGravatarに登録しているとは考えにくく、結局はデフォルトアバターばかりが表示されることになって意味がありません。

そこで、「WP User Avatar」というプラグインを使って、購入者がマイページからアバターを簡単に変えられるようにします。

WP User Avatar

アバターを変更するページのイメージは以下の通りです。

WooCommerceのレビューのアバター変更ページ

ファイルを選択して「アップロード」をクリックすると、アバターが変わります。

「画像を削除」をクリックしてから「プロフィールの更新」をクリックすれば、デフォルトのアバターに戻ります。

まずは、WP User Avatarのプラグインをインストールして、管理画面の「アバター」⇒「設定」から初期設定を行います。

WP User Avatarの設定

重要なのは「寄稿者・購読者によるアバター画像アップロードを許可」にチェックを入れることです。そうしないと、マイページからアバターを変更できません。

アップロードサイズやデフォルトのアバターなどは自由に設定してください。

ここからは、マイページにアバターの変更ページを作成します。

WooCommerceのマイページにアバターの変更を追加

まずは、上のようにマイページのメニューに「アバターの変更」を追加します。

// マイページのメニューに「アバターの変更」を追加
function custom_account_menu() {
	$menuOrder = array(
        'dashboard'          => 'トップ', // __( 'Dashboard', 'woocommerce' )
        'orders'             => '過去の注文', // __( 'Orders', 'woocommerce' )
        'downloads'          => __( 'Downloads', 'woocommerce' ),
        'edit-address'       => __( 'Addresses', 'woocommerce' ),
        'edit-account'       => 'アカウントの変更', // __( 'Account details', 'woocommerce' )
        'avatar'             => 'アバターの変更',
        'customer-logout'    => __( 'Logout', 'woocommerce' ),
	);
	return $menuOrder;
}
add_filter('woocommerce_account_menu_items', 'custom_account_menu');

woocommerce_account_menu_itemsというフィルターフックを使い、マイページのメニューを定義します。

メニューの配列に「avatar」を追加しています。また、不要なメニューは配列から削除したり、「トップ」や「過去の注文」のようにメニューの名称を変えることも可能です。

// 「アバターの変更」のエンドポイントを追加
function custom_account_menu_avatar_endpoints() {
	add_rewrite_endpoint('avatar', EP_ROOT | EP_PAGES);
}
add_action('init', 'custom_account_menu_avatar_endpoints');

次に、add_rewrite_endpointでエンドポイントを追加します。

これによって「my-account(マイページのスラッグ)/avatar」といったURLでページが表示できるようになります。

functions.phpに上記のプログラムを記述したら、「設定」⇒「パーマリンク設定」を開いて、そのまま「変更を保存」ボタンをクリックします。すると、リライトルールが再生成されて、このURLが有効になります。

以上の手順によって、アバターの変更というメニューにアクセスできるようになりました。ここからは、アバターを変更するページの中身を設定していきます。

// 「アバターの変更」のページタイトルを設定
function avatar_title() {
	return 'アバターの変更';
}
add_filter('woocommerce_endpoint_avatar_title', 'avatar_title');

ページのタイトルを変更するには、woocommerce_endpoint_{エンドポイント名}_titleというフィルターフックを使います。

// 「アバターの変更」のページの中身を設定
function edit_avatar() {
	echo do_shortcode('[avatar_upload]');
}
add_action('woocommerce_account_avatar_endpoint', 'edit_avatar');

肝心のページの中身は、woocommerce_account_{エンドポイント名}_endpointというアクションフックを使います。

WP User Avatarのプラグインにはavatar_uploadというアバターを変更するフォームを表示するショートコードが用意されているので、do_shortcodeで実行します。

補足

ショートコードを実行するだけではなく、get_template_partで外部ファイルを呼び出すことも可能です。WP User Avatarのフォームは少し分かりにくいので、フォームの上下にアバターを変更する手順などを記載しても良いかもしれません。

// 「アバターの変更」のクエリ変数を追加
function avatar_query_vars($vars) {
	$vars['avatar'] = 'avatar';
	return $vars;
}
add_filter('woocommerce_get_query_vars', 'avatar_query_vars');

そのままではエンドポイントのURLか判定するis_wc_endpoint_url('avatar')がfalseになってしまい、パンくずリストに「マイページ」が含まれません。

そこで、woocommerce_get_query_varsというフィルターフックでクエリ変数を追加します。ページタイトルを設定していれば、以下のように「マイページ」が含まれていると思います。

アバターの変更のパンくずリスト

最後に、アバターの画像をカスタマイズする方法を紹介します。

// レビューに表示するアバターを編集する
remove_action('woocommerce_review_before', 'woocommerce_review_display_gravatar', 10);
add_action('woocommerce_review_before', 'woocommerce_review_display_avatar', 10);
function woocommerce_review_display_avatar($comment) {
	$avatar_url = get_avatar_url($comment->user_id, ['size' => '512']);
	echo '<img src="'. esc_url($avatar_url) .'" alt="アバター" class="avatar" />';
}

woocommerce_review_beforeというアクションフックを使うと、表示するアバターのimgタグを変えられます。

上の例では、サムネイルからフルサイズの画像に変えて、alt属性とclass属性を設定しています。

後は、CSSを使って好きなようにアバターのデザインを変えてみてください。例えば、「border-radius: 50%;」という指定をすれば、丸いアバターを表示できます。

匿名でレビューする

WooCommerceでレビューをすると、「表示名(ブログ上の表示名)」がレビューをした人の名前として表示されます。

「表示名」はマイページから変更できますが、アカウントを登録したときの初期状態では「姓+名」という形式になっています。

そのため、商品を購入した人がそのままレビューを行うと、意図せずに本名が公開される可能性があります。

この問題を回避する方法は、いくつか考えられます。

  • アカウント登録時に表示名に「匿名」を自動で設定し、後でマイページから変えてもらう
    マイページの「○○さん」という表示も「匿名」になる
  • レビューを表示するときに名前を表示しない
    名前がある方がレビューの信頼性は上がると思います。
  • レビューを投稿するときに匿名にするか選んでもらう

今回は、最後の匿名にするか選ぶ方法を紹介します。

WooCommerceのネットショップにおいて匿名でレビューする

上のように、レビューをするときに「匿名でレビューする」にチェックを入れると、レビューの名前に「匿名」が表示されます。

補足

管理画面でコメントを確認するときも「匿名」になります。ただし、WordPressのユーザーは同じメールアドレスを登録できないので、「ユーザー」⇒「ユーザー一覧」からメールアドレスでユーザーを検索すれば、コメントをした人の本名などが分かります。

まずは、レビューのフォームに匿名の選択欄を追加します。

// 匿名の選択欄を追加する
function add_anonymous_field($review_form) {
	$review_form['comment_notes_after'] = '<div class="comment_form_anonymous"><label><input type="checkbox" name="anonymous" value="1"> 匿名でレビューする</label></div>';
	return $review_form;
}
add_filter('woocommerce_product_review_comment_form_args', 'add_anonymous_field');

woocommerce_product_review_comment_form_argsというフィルターフックを使うと、レビューのフォームを変えられます。

comment_notes_afterというキーにチェックボックスのinputタグを設定すれば、フォームの最後に選択欄が表示されると思います。

次に、匿名が選択されたときに、データベースに「匿名」を登録するプログラムを記述します。

// レビューの名前に「匿名」を登録する
function save_anonymous_field($comment_id) {
    if(isset($_POST['anonymous']) && $_POST['anonymous'] == '1') {
		$comment_data['comment_ID'] = $comment_id;
		$comment_data['comment_author'] = '匿名';
		wp_update_comment($comment_data);
	}
}
add_action('comment_post', 'save_anonymous_field');

comment_postというアクションフックは、レビューがデータベースに登録された後に呼ばれます。

$_POSTでチェックボックスの値を取得し、匿名が選択されたときだけcomment_authorに「匿名」を設定して、wp_update_commentでレビューを更新しています。

レビューの回数を制限する

WooCommerceはレビューの回数に制限がありません。そのため、いたずらで何度もレビューすることができてしまいます。

もちろん、WordPressの管理画面からレビューを否認したり、削除することはできますが、少し面倒です。

ここでは、一つの商品に同じ人が一度しかレビューできないように制限する方法を紹介します。

WooCommerceのネットショップにおいてレビューの回数を制限する

上のように、既にレビューをしている商品に対しては、レビューのフォームを非表示にします。

// レビューのフォームを非表示にする
function hidden_review_form($review_form) {
	$user = wp_get_current_user();
	$usercomment = get_comments(array('user_id' => $user->ID, 'post_id' => get_the_ID()));
	if($usercomment) {
		$review_form['class_form'] = 'hidden';
	}
	
	return $review_form;
}
add_filter('woocommerce_product_review_comment_form_args', 'hidden_review_form');

匿名でレビューするときと同様にwoocommerce_product_review_comment_form_argsを使うので、プログラムをまとめても構いません。

現在ログインしている購入者のユーザーIDと現在閲覧している商品IDをもとにget_commentsでコメントを取得して、既に存在する場合はレビューのformタグに「hidden」というclass属性を設定しています。

後は、style.cssなどでhiddenのclass属性に対して「display: none;」を指定すれば良いです。(その他に余白やマージンなどの微調整は必要です。)

これでフォームは見えなくなりましたが、ブラウザの開発者ツールなどを利用してレビューのフォームを表示して、強引にレビューをすることは可能です。

そこで、以下のプログラムを記述します。

// レビューが登録済みの場合はエラーを表示する
function check_already_review($comment_post_id) {
	$user = wp_get_current_user();
	$usercomment = get_comments(array('user_id' => $user->ID, 'post_id' => $comment_post_id));
	if ($usercomment){
		wp_die('既にレビューは投稿されています。');
	}
}
add_action('pre_comment_on_post', 'check_already_review');

レビューがPOSTされる前に呼ばれるpre_comment_on_postというアクションフックを使います。

先ほどと同じようにレビューが済んでいるか確認を行い、もしも済んでいる場合にはwp_dieで処理を中断します。

WooCommerceでレビューの重複エラー

実際に重複したレビューを行うと、上のようなエラー画面が表示されます。

補足

WooCommerceのテンプレートを修正すれば、CSSで見た目だけ非表示にするのではなく、formタグ自体を出力させないことも可能です。しかし、WooCommerceのアップデートでテンプレートが変わる可能性を考慮して、このようなやり方にしました。

最新のレビューから順番にページ送りする

ここでは、WooCommerceのレビューにページャーを設置して、件数が多いときにページ送りできるようにします。

WordPressのコメント機能はページャーを設置したときの表示順序が難しく、上手くいかない経験をした方も多いと思います。

一般的には、以下のように最新のレビューから順番に表示して、ページ送りをするごとに古くなっていくのが自然だと思います。しかし、これがなかなか難しいです。

WooCommerceのレビューのページャー
WooCommerceのレビューのページャー(次ページ)

WooCommerceのレビューにページャーを設置するには、管理画面の「設定」⇒「ディスカッション」から設定を行います。

WooCommerceのレビューにページャーを設置する設定

サンプルでは3件ごとにページ送りしていますが、もう少し多い方が使いやすいと思います。

「最初のページをデフォルトで表示する」、「新しいコメントを各ページのトップに表示する」を設定しているので、想定通りの表示順序になるかと思いきや、実際には以下のようになります。

WooCommerceのレビューで表示順序がおかしいページャー
WooCommerceのレビューで表示順序がおかしいページャー(次のページ)

想定通りの表示順序にするには、functions.phpに以下のプログラムを記述します。

// レビューの配列を逆順にする
function reverse_comments_array($comments) {
  return array_reverse($comments);
}
add_filter('comments_array', 'reverse_comments_array');

// レビューを取得するときのorderに降順(DESC)を指定する
function desc_comments_order($comment_args) {
    $comment_args['order'] = 'DESC';
    return $comment_args;
}
add_filter('comments_template_query_args', 'desc_comments_order');

これで想定通りの表示順序になりますが、レビューを投稿した後に、最新ページではなく最終ページに移動するという問題が発生します。

致命的な問題ではありませんが、違和感のある動きなので修正しておきます。

// レビューを投稿した後に当該レビューに移動する
function after_review_redirect($location, $comment) {
	$location = esc_url(get_permalink($comment->comment_post_ID)) . '#comment-' . $comment->comment_ID;
	return $location;
}
add_filter('comment_post_redirect', 'after_review_redirect', 10, 2);

レビューを投稿した後に呼ばれるcomment_post_redirectというフィルターフックで、現在投稿したレビューに対するURLをリダイレクト先に設定しています。

補足

WordPressのコメントのページ送りは、もっと良いやり方があるかもしれません。気になる方は調べてみてください。

レビューの履歴と削除

最後におまけとして、レビューの履歴を確認したり、間違えて投稿したレビューを削除できる機能をマイページに作成します。

WooCommerceのレビュー履歴を表示する機能

上の画面キャプチャがレビューの履歴を表示するページのイメージです。レビューの日付、商品名、商品画像、評価、レビューのコメントを確認できます。

商品名はリンクになっており、クリックすると商品の詳細ページに移動します。

補足

レビューの履歴を表示する場合は、横のスペースを確保するためにカテゴリーなどのサイドバーを非表示にするのが良いと思います。

WooCommerceのレビューを削除する機能

削除したいレビューにチェックを入れて、「削除」ボタンをクリックすると、レビューが削除されます。

レビューの回数はリセットされるので、再び同じ商品にレビューができます。

レビュー履歴が存在しないメッセージ

レビューが1件もない場合はメッセージを表示します。また、レビューをした商品が削除されている場合には、そのレビューを非表示にします。

不正なリクエストのエラーメッセージ

悪意のある人が他人のレビューを削除しようとしている場合には、不正なリクエストとしてエラーメッセージを表示します。

ここからは、レビューの履歴と削除機能の作り方を紹介します。

マイページのメニューにレビューの履歴を追加するところは、アバターの変更と全く同じ流れなので省略します。エンドポイントやページタイトルなどを設定してください。

レビューの履歴のメニューをクリックしたときに表示されるプログラムは以下の通りです。

.center {
    text-align: center;
}

.review_history_row {
    display: table;
    width: 100%;
}

.review_history_row.title {
    background-color: #70b3e0;
    text-align: center;
    color: #fff;
}

.review_history_row.title .review_history_item:first-of-type  {
    border: solid 1px #E5E5E5;
}

.review_history_row.title .review_history_item {
    border-top: solid 1px #E5E5E5;
    border-right: solid 1px #E5E5E5;
    border-bottom: solid 1px #E5E5E5;
    word-break : break-all !important;
}

.review_history_row .review_history_item:first-of-type {
    border-right: solid 1px #E5E5E5;
    border-bottom: solid 1px #E5E5E5;
    border-left: solid 1px #E5E5E5;
}

.review_history_row .review_history_item {
    display: table-cell;
    vertical-align: middle;
    padding: 5px;
    border-right: solid 1px #E5E5E5;
    border-bottom: solid 1px #E5E5E5;
    word-break : break-all !important;
}

.review_history_row .review_history_item .review_history_image {
    width: 100%;
    height: 100px;
    object-fit: cover;
}

.review_history_row .review_history_item .star-rating {
    margin: 0 auto;
}

.delete_review_button {
    margin-top: 1em;
    float: right;
}

.delete_review_error {
    margin-bottom: 1.5em;
    color: red;
}

.delete_review_error::before {
    font-family: 'Font Awesome 5 Free';
    font-weight: 900;
    content: "\f06a";
    margin-right: 7px;
}
注意

参考としてCSSを掲載しますが、このままでは十分ではありません。デザインは適当で、デバイスサイズなども考慮していません。

function show_review_history() {
		
	$user = wp_get_current_user();
	$args = array(
		'user_id'  => $user->ID,
		'post_type' => 'product',
		'orderby' => 'comment_date',
		'order' => 'DESC'
	);
	
        $is_error = false;
	if(!empty($_POST['delete_review_id_list'])) {
		$before_comments = get_comments($args);
		foreach($before_comments as $comment) {
			$comment_id_list[] = $comment->comment_ID;
		}
		
		// 存在しないコメントIDがあればエラー
		foreach($_POST['delete_review_id_list'] as $delete_review_id) {
			if(!in_array($delete_review_id, $comment_id_list)) {
				$is_error = true;
				echo '<p class="delete_review_error">不正なリクエストです。</p>';
                                break;
			}
		}
		
		// 不正なリクエストでなければ削除
		if(!$is_error) {
			foreach($_POST['delete_review_id_list'] as $delete_review_id) {
				// ゴミ箱からの強制削除はしない
				wp_delete_comment($delete_review_id);
			}
		}
	}
	
	// 通常表示または削除後のコメントを取得
	$comments = get_comments($args);
	foreach($comments as $comment) {
		$comment_status_array[$comment->comment_post_ID] = get_post_status($comment->comment_post_ID);
	}
	
	// 公開済みの商品に紐づくレビューのみ表示
	if(!empty($comments) && in_array('publish', $comment_status_array)) {
		echo '<form method="post" action="review-history"><div class="review_history_row title">';
		echo '<div class="review_history_item" style="width: 5%"></div>';
		echo '<div class="review_history_item" style="width: 13%">日付</div>';
		echo '<div class="review_history_item" style="width: 17%">商品名</div>';
		echo '<div class="review_history_item" style="width: 15%">商品画像</div>';
		echo '<div class="review_history_item" style="width: 15%">評価</div>';
		echo '<div class="review_history_item" style="width: 35%">レビュー</div>';
		echo '</div>';	
		foreach ($comments as $comment) {
			if($comment_status_array[$comment->comment_post_ID] == 'publish') {
				$product = wc_get_product($comment->comment_post_ID);	
				$product_url = esc_url(get_permalink($comment->comment_post_ID)). '#comment-' . $comment->comment_ID;
				$img_url = esc_url(wp_get_attachment_url($product->image_id));
				$rating = get_comment_meta($comment->comment_ID, 'rating');
				echo '<div class="review_history_row">';
				echo '<div class="review_history_item center" style="width: 5%;"><input type="checkbox" name="delete_review_id_list[]" value="' . $comment->comment_ID .'"></div>';
				echo '<div class="review_history_item center" style="width: 13%;">' . date('Y/m/d', strtotime($comment->comment_date)) . '</div>';
				echo '<div class="review_history_item center" style="width: 17%;"><a href="' . $product_url . '">' . $product->name . '</a></div>';
				echo '<div class="review_history_item center" style="width: 15%;"><img src="' . $img_url . '" alt="' . $product->name . '" class="review_history_image" /></div>';
				echo '<div class="review_history_item center" style="width: 15%;"><div class="star-rating">' . wc_get_star_rating_html($rating[0]) . '</div></div>';
				echo '<div class="review_history_item" style="width: 35%">' . $comment->comment_content . '</div>';
				echo '</div>';			
			}
		}
		echo '<input type="submit" value="削除" class="delete_review_button"></form>';
		
		if(!empty($_POST['delete_review_id_list']) && !$is_error) {
			// これがないと削除後にリロードすると不正なリクエストになる
			wp_safe_redirect(get_the_permalink() . '/review-history');
		}
	}else {
		echo '<p class="delete_review_error">レビューが存在しないか、レビューをした商品が削除されています。</p>';
	}
}
add_action('woocommerce_account_review-history_endpoint', 'show_review_history');

$_POSTで削除対象のコメントIDを取得して、wp_delete_commentによってレビューを削除しています。

wp_delete_commentには$force_deleteという引数があってゴミ箱から完全に削除することもできますが、それは指定せずに万が一のときは管理画面から復元できるようにしています。

get_commentsでログインしているユーザーのコメントを取得して、そこに含まれないコメントIDが削除対象として要求された場合、不正なリクエストとして処理を中断します。

履歴を表示している部分は、foreach文でレビューや商品情報をHTMLに設定しているだけです。

注意

テストを十分にやっているわけではありません。削除処理を伴うので十分にテストを行い、不備があれば修正してください。クロスサイトリクエストフォージェリの対策としてnonceを使った方が良いかもしれません。

まとめ

この記事では、WooCommerceのレビュー機能をカスタマイズする方法を紹介しました。

本格的にカスタマイズしようと思えばやることが多く、WooCommerce専用の優れたテーマを使って、作業負担を減らすことも大切です。

また、評価の表を掲載したり、レビュー依頼のメール送信やレビューのクーポンを配布する場合には、「Customer Reviews for WooCommerce」というプラグインもあります。気になる方は調べてみてください。

なお、私の理解が足りていない部分もあるので、記事の内容は間違っている可能性があります。全て自己責任で参考にしてください。

コメント(現在、質問は受け付けていません)

コメントする

CAPTCHA


目次
閉じる