【修正】WordPressのゲストアバターをいろんな画像で表示するカスタマイズ

2019/3/19 get_avatar()を使う仕様に変更しました。

wordpressで利用できる自動生成アバターをオリジナルの画像にしてコメント欄をにぎやかにしたい。

WordPressで運営しているブログにいろんな方からコメントをいただくとうれしいですが、Gravatar登録のない場合、同じデフォルトアバターになってしまって味気なく感じませんか?

あらかじめWordpressで用意されている自動生成アバターならいろんな画像を割り当ててくれるのですが選択肢がどれもいまいち。Idenctionがシンプルでまだ使いやすいので利用されてる方よく見かけますね。

デフォルトアバターをオリジナル画像に設定するカスタマイズは多く知られていますが、今回は自動生成アバターのようにゲストのお名前によって表示アバターを変化させるカスタマイズを考えてみました。

WordPress4.8で確認。PHP・FTPの知識が必要です。
get_avatar_data()は4.2から導入された関数ですので、それ以前のバージョンでは使えません。

functions.phpへコードを書き込み、FTPでアバター画像をアップロードしてください。
このサンプルでは19通りのアバターを使用します。

実際に運用しているサイト(サンプルではないのでテスト投稿はお控えください。)

メールアドレスが未入力だったりgravatarが設定されていない場合に入力された名前を元に用意してある画像を表示させます。画像の数が用意できないので19通りになりましたが、ファイル名を作る部分をカスタマイズすることでお好みの数の画像を使うことができます。

スポンサーリンク

コードと使い方

画像の準備

avatar_1.png~avatar_19.pngの画像を用意。

そのままコピペする場合はテーマディレクトリ(wp-contents/theme/使用中のワードプレステーマのディレクトリ)以下にavatarというディレクトリを作ってそこにFTPでアップロードしてください。

別の場所に画像を用意する場合には2行目を次のように修正。

ブラウザからメディアにアップロードする場合は

$avatar_dir = ”https://サイトのアドレス/wp-content/uploads/”;
(アップロード先は一例です。画像のアドレスを確認してください。)

サイトURL直下にavatarディレクトリを作った場合には

$avatar_dir = site_url().’/avatar/’;

となります。

functions.phpに以下のコードをコピペ。

function new_get_avatar($avatar, $id_or_email, $size, $default, $alt){
$avatar_dir = get_stylesheet_directory_uri().'/avatar/'; //アバター画像のある場所

if ( is_object( $id_or_email ) && isset( $id_or_email->user_id ) && ! empty($id_or_email->user_id) or is_int($id_or_email) && ! empty($id_or_email)){
	return $avatar;
	}	
	elseif ( isset( $id_or_email->comment_author_email ) && ! empty( $id_or_email->comment_author_email )) {
 	$hash = md5( strtolower( trim( $id_or_email->comment_author_email) ) );
	if(is_ssl()){$uri = 'https://www.gravatar.com/avatar/' . $hash . '?d=404';}
	else{
	$uri = 'http://www.gravatar.com/avatar/' . $hash . '?d=404';}
	$headers = @get_headers($uri);
	if (preg_match("|200|", $headers[0])) {
	return $avatar;
	}
}
if(is_object($id_or_email) && isset ($id_or_email->comment_author)){
	$word = "1".substr(preg_replace("/[^0-9]+/","",md5($id_or_email->comment_author)),1,9);
	$userid1 =substr($word,1,1);
	$userid2 =substr($word,6,1);
	$userid = $userid1 + $userid2 + 1;
	$avatar_url = $avatar_dir.'avatar_'.$userid.'.png';
	$avatar ="<img alt='" . esc_attr( $alt ) . "' src='" . $avatar_url . "' class='avatar avatar-{$size} photo' height='{$size}' width='{$size}' />";
}
return $avatar;
}
add_filter('get_avatar','new_get_avatar',1,5);


解説

ユーザーIDが定義されている場合は書き換えない

Gravatarを設定していなくても他のプラグインで画像を設定している場合などそちらを優先するようにWordpressのユーザーであればGravatarの有無にかかわらず無条件で書き換えないようにしました。何も設定していない場合にはディスカッションで設定されているデフォルトのアバターが表示されます。

メールアドレスが記入されている場合はGravatarがあるかチェック

メールアドレスからgravatarのURLを生成し画像が存在しているかを確認する方法はWordPress Codexにサンプルがありましたのでほぼそのまま使いました。

Gravatar が存在するかのチェック – Gravatar の使い方

gravatarが存在していた場合のみあらかじめ定義した$check_avatarをTRUEにし$avatarの内容はは変更せずそのまま戻します。

アバターの書き換え

コメントループ内でのみ投稿者の名前をもとにランダムっぽく画像URLを作成し、imgタグに書き出します。

テーマによってはコメントループ外で直接ユーザーIDやE-mailを指定しアバターを表示していることがあるので、その場合は変更されずデフォルトアバターが表示されます。(テストしたデフォルトテーマのtwentynineteenだと小さく表示されているところが変更できませんでした)

名前を数値化して1~19までの数字に

$word = "1".substr(preg_replace("/[^0-9]+/","",md5($id_or_email->comment_author)),1,9);
$userid1 =substr($word,1,1);
$userid2 =substr($word,6,1);
$userid = $userid1 + $userid2 + 1;
$avatar_url = $avatar_dir.'avatar_'.$userid.'.png';

$word = "1".substr(preg_replace("/[^0-9]+/","",md5($id_or_email->comment_author)),1,9);

名前($id_or_email->comment_author)をMD5でハッシュ値(文字列)に変換、その中から数字以外を削除して9文字取り出し頭に1を足して10桁の数字にしました。
(1を足しているのはなんとなく一文字目が0になるのが嫌だったからです)


$userid1 =substr($word,1,1);
$userid2 =substr($word,6,1);
$userid = $userid1 + $userid2 + 1;

10桁の数字から2つめ($userid1)と7つめ($userid2)を足してさらに1を足しました。

0~9の数字を2つ足して、それに1をプラスするので$useridは1(0+0+1)~19(9+9+1)になります。これで19種類の画像を割り当てる準備ができました。

使用する画像の数を変更したり、名前以外の要素を利用するならこのへんに手を加えてください。

何度もテストしましたが問題点があればご指摘ください。

2019年3月に大幅に変更しました。

URLだけを書き換えたくget_avatar_data()に対してカスタマイズしていましたが、一つのアバターを表示させるのに何度かget_avatar_data()を呼び出しているっぽいのが気になったので最終的なimgタグを出力するget_avatar()に対してのカスタマイズに変更しました。

修正前のコードも掲載しておきます。
ちょこちょこ問題がありますので、何かの参考程度に(なるのかな)。

function new_get_avatar_data($args,$id_or_email){
$check_avatar ="";
$user = null;
if($args['found_avatar'] == true){
	if ( ! empty( $id_or_email->user_id )){
		$user = get_user_by( 'id', (int) $id_or_email->user_id );
		$email = $user->user_email;
		}
	
	if ( ( ! $user || is_wp_error( $user ) ) && ! empty( $id_or_email->comment_author_email ) ) {
		$email = $id_or_email->comment_author_email;
		}
 	
 	if(! empty($email)){
 		$hash = md5( strtolower( trim( $email ) ) );
		}
	
	$uri = 'http://www.gravatar.com/avatar/' . $hash . '?d=404';
	$headers = @get_headers($uri);
	
	if (preg_match("|200|", $headers[0])) {
		$check_avatar = TRUE;
		}

	}
if(is_object($id_or_email) && isset( $id_or_email->user_id ) && empty($check_avatar)){
	if(isset ($id_or_email->comment_author)){
		$word = "1".substr(preg_replace("/[^0-9]+/","",md5($id_or_email->comment_author)),1,9);
		$userid1 =substr($word,1,1);
		$userid2 =substr($word,6,1);
		$userid = $userid1 + $userid2 + 1;
		$args['url'] = get_stylesheet_directory_uri().'/avatar/avatar_'.$userid.'.png';
		}
	return $args;
	}
	else{
	return $args;
	}
}
add_filter('get_avatar_data','new_get_avatar_data',10,2);

コメント

  1. まちゃとら より:

    はじめまして。
    まちゃとらと申します。

    wordpressのデフォルトアバターの変更方法、すごく参考になりました!

    ひとつご質問させて頂きたいのですが、wordpressのコメント欄に「男性」と「女性」のラジオボタンを設置し、その選択によって男性と女性の画像をデフォルトアバターとして表示したいと考えています。

    この場合、functions.phpにはどのような記述をすれば良いのでしょうか?

    お手数をお掛けしてしまい、誠に申し訳ございませんがご教授頂けましたら幸いです!
    よろしくお願い致します!

    • minaparu より:

      まちゃとらさま、コメントの承認が遅くなり大変申し訳ありませんでした。

      ご質問の件ですが、コメントフォームの改造とアバター表示の改造が必要になりますね。少し調べてみましたが形にするのは私の力量ではちょっと難しそうかな??
      お役に立てず申し訳ないです。
      ただ、できたら面白そうなのでチャレンジしてみますね。もし上手く行けば記事にします。

  2. ななし より:

    期待してます

    • minaparu より:

      ななし様、コメントの承認がおそくなりました。
      選択式は実装できそうかなと思ったのですが、ランダム表示とは違い受け取ったアバター情報の処理も絡んでくるので
      やらなきゃいけない処理が多そう…と開発の手がとまってます、ごめんなさい。
      https://blog.minaworld.net/archives/gender_choice_customize/

  3. とくえもん より:

    こんにちわ。

    上記のコードを使わせていただいております。

    導入してすぐは、gravatarの画像がある場合は、その画像がアバター画像になっていたのですが、今はgravatarの画像がある場合でもすべて、ランダム表示になっています。

    この問題を切り分けて行くにはどのような手順で調査したらよろしいでしょうか?

    • minaparu より:

      とくえもん様コメントありがとうございます。

      ご指摘の症状はメールアドレスやユーザーIDのチェックをスルーしてURLが書き換えられているみたいなので、前半の処理・・・冒頭の分岐で使っている$args[‘found_avatar’]の部分が怪しいかなという気がします。

      いろいろテストしてみて、その状態が再現できなかったのでテンプレートやプラグインとの競合も考えられますね。
      テンプレートによっては$args[‘found_avatar’]が定義されないことがある、というのが一番可能性が高いと思います。

      最初の分岐if($args[‘found_avatar’] == true){…}はまるっと省いて、ここに内包されている部分だけにしても動きます。がもともと公開していたコードはダメな部分があって変数未定義のエラー吐き出しまくります。すいません。

      このカスタマイズの内容はそこも含めてちょっと気になる部分もあって修正したいなと思っていたので、get_avatar_data()ではなくget_avatar()を使用したバージョンを公開しました。

      もしget_avatar_data()バージョンをご使用の場合は
      1行目の
      function new_get_avatar_data($args,$id_or_email){

      から

      真ん中あたりの
      if(is_object($id_or_email) && isset( $id_or_email->user_id ) && empty($check_avatar)){

      の間を以下のコードに書き換えて様子を見てください(変数未定義修正済み)

      $check_avatar ="";
      $user = $hash = null;
      	if ( ! empty( $id_or_email->user_id )){
      		$user = get_user_by( 'id', (int) $id_or_email->user_id );
      		$email = $user->user_email;
      		}
      	
      	if ( ( ! $user || is_wp_error( $user ) ) && ! empty( $id_or_email->comment_author_email ) ) {
      		$email = $id_or_email->comment_author_email;
      		}
       	
       	if(! empty($email)){
       		$hash = md5( strtolower( trim( $email ) ) );
      		}
      	
      	$uri = 'http://www.gravatar.com/avatar/' . $hash . '?d=404';
      	$headers = @get_headers($uri);
      	
      	if (preg_match("|200|", $headers[0])) {
      		$check_avatar = TRUE;
      		}
      • とくえもん より:

        minaparuさま

        ご返信ありがとうございます!
        具体的なコードまでいただいて・・・。

        いろいろ試してみましたが、解決しませんでした。

        現状は、上記のコードをに変更しております。
        試したパターンを整理いたします。

        1.現在のテーマ(SANGO)で旧コードを利用
        →ランダム表示はされるが、gravatar画像を表示してくれない。

        2.現在のテーマ(SANGO)で新コードを利用
        →ランダム表示はされるが、gravatar画像を表示してくれない。

        3.テーマをTwenty Nineteenにして、コードを貼らない。
        →ランダム表示はされないが、gravatar画像を表示してくれた。
        (当たり前ですが・・・。)

        4.テーマをTwenty Nineteenにして、新・旧コードを貼る。
        →ランダム表示はされるが、gravatar画像を表示してくれない。

        5.テーマをTwenty Nineteenにして、新・旧コードを貼る。全プラグイン停止。
        →ランダム表示はされるが、gravatar画像を表示してくれない。

        ご参考にならないかと思いますが、該当のページをお知らせいたします。
        https://furutoku.com/about/?trashed=1&ids=95

      • minaparu より:

        とくえもん様、検証ありがとうございます!
        そして解決しませんでしたか・・・(´ω`;;)

        新コードというのは、コメント欄に書いた修正ではなく本文のget_avatar()バージョンですか?
        コード前半部分が無視されているようなのでもっとユーザーを特定するための条件をつければいいのかな。プラグインなしのデフォルトテーマで同様の現象とのことなのでこちらでも再現できればいいのですが…。
        とくにデータベースに修正を加えるようなカスタマイズでもないのでサーバーの仕様などは関係ないと思うのですよね。WP本体のアップデートで仕様が変わった部分があるのかな?ちょっと今時間とれないんですがまた確認してみますね。お役に立てずすいません!

        –追記

        もし、ゲストの方のGravatarを無視しても構わないのであれば前半を省いた次のコードもお試しください。

        function new_get_avatar($avatar, $id_or_email, $size, $default, $alt){
        $avatar_dir = get_stylesheet_directory_uri().'/avatar/'; //アバター画像のある場所
        
        if(is_object($id_or_email) && isset ($id_or_email->comment_author) && empty($id_or_email->user_id)){
        $word = "1".substr(preg_replace("/[^0-9]+/","",md5($id_or_email->comment_author)),1,9);
        $userid1 =substr($word,1,1);
        $userid2 =substr($word,6,1);
        $userid = $userid1 + $userid2 + 1;
        $avatar_url = $avatar_dir.'avatar_'.$userid.'.png';
        $avatar = "<img alt='" . esc_attr( $alt ) . "' src='" . $avatar_url . "' class='avatar avatar-{$size} photo' height='{$size}' width='{$size}' />";
        }
        return $avatar;
        }
        add_filter('get_avatar','new_get_avatar',1,5);
        

        WordPressのユーザーによるコメント以外は画像を書き換えるというカスタマイズです。
        $id_or_email->user_idが0(空っぽ)の人のアバターを書き換えるのですが、これまでのカスタマイズでもこの変数を利用していたのでうまく動くかどうか(´ω`;)

  4. とくえもん より:

    minaparuさま

    何度も対応いただいてすみません。。。

    新コードは、本文のget_avatar()バージョンでした。

    そして・・・

    いただいた「ゲストのGravatar無視バージョン」を試しましたら・・・

    いけました!!
    ゲストの方は、とりあえず気にせずこちらを利用したいと思います。

    ありがとうございました!

    • minaparu より:

      とくえもん様

      ひとまず意図通りの表示ができてよかったです!
      今回コメントいただいたことで問題点を修正することができました。ありがとうございました!