この記事にはおすすめ商品の広告があります

WordPressはアバター(プロフィール画像)の管理を《Gravatar》という外部サービスに委託しています。この仕様のため、管理画面から直接アバターを設定することは出来ません。

「アバター画像は自分のサイトで使うためだけに設定したい」
「他のサイトにコメントはしないorしたとしても別にアバター表示は要らない」
「Gravatarに登録するのが嫌だ」

という方のために、ユーザー画面から簡単にプロフィール画像を設定出来るようにするカスタマイズをご紹介します。

目的

  • プラグインやGravatarなどの外部サービスを利用せず、ユーザー画面から自由にプロフィールを設定出来るようにする。
  • 自分のサイト内だけで使えるローカルなアバターを利用可能にする。
  • メディアライブラリを介して画像の選択・アップロード・削除が管理画面で完結出来るようになる。
  • Gravatarが設定済の場合でも優先して表示される。(表示上の優先でありGravatarの登録内容には影響ありません)

実装手順

前提条件

このカスタマイズはfunctions.phpを使用します。テーマファイルに対して機能を追加するので、テーマを変更すると機能しなくなります。
親テーマのfunctions.phpを直接変更するのは非推奨です。子テーマを用意し、その中にfunctions.phpをアップロードして使いましょう。
また、念のため作業前にバックアップを取っておくことを推奨します。

1

functions.phpにコードを追加

子テーマのfunctions.phpに下記のコードを追加します。

functions.php
// ================================
// カスタムプロフィール画像 機能
// ================================

// ユーザープロフィール画面にカスタムフィールドを追加
add_action('show_user_profile', 'add_custom_profile_photo_field');
add_action('edit_user_profile', 'add_custom_profile_photo_field');

function add_custom_profile_photo_field($user) {
    $profile_photo_id = get_user_meta($user->ID, 'profile_photo_id', true);
    $profile_photo_url = '';
    
    if ($profile_photo_id) {
        $profile_photo_url = wp_get_attachment_url($profile_photo_id);
    }
    ?>
    <h3>プロフィール画像設定</h3>
    <table class="form-table">
        <tr>
            <th><label for="profile_photo">アバター</label></th>
            <td>
                <div id="profile-photo-container">
                    <div id="profile-photo-preview" style="margin-bottom: 10px;">
                        <?php if ($profile_photo_url): ?>
                            <img src="<?php echo esc_url($profile_photo_url); ?>" 
                                 style="width: 100px; height: 100px; object-fit: cover; border-radius: 50%;" 
                                 alt="プロフィール画像">
                        <?php else: ?>
                            <div style="width: 100px; height: 100px; background-color: #f0f0f0; border-radius: 50%; display: flex; align-items: center; justify-content: center; color: #666;">
                                画像なし
                            </div>
                        <?php endif; ?>
                    </div>
                    <input type="hidden" id="profile_photo_id" name="profile_photo_id" value="<?php echo esc_attr($profile_photo_id); ?>">
                    <button type="button" class="button" id="upload-profile-photo">画像を選択</button>
                    <?php if ($profile_photo_id): ?>
                        <button type="button" class="button" id="remove-profile-photo">画像を削除</button>
                    <?php endif; ?>
                </div>
                <p class="description">
                    プロフィール画像を設定すると、Gravatarの代わりに使用されます。<br>
                    推奨サイズ: 150x150px以上の正方形画像
                </p>
            </td>
        </tr>
    </table>
    
    <script>
    jQuery(document).ready(function($) {
        var mediaUploader;
        
        // 画像選択ボタンクリック
        $('#upload-profile-photo').click(function(e) {
            e.preventDefault();
            
            if (mediaUploader) {
                mediaUploader.open();
                return;
            }
            
            mediaUploader = wp.media({
                title: 'プロフィール画像を選択',
                button: {
                    text: '画像を選択'
                },
                multiple: false,
                library: {
                    type: 'image'
                }
            });
            
            mediaUploader.on('select', function() {
                var attachment = mediaUploader.state().get('selection').first().toJSON();
                
                $('#profile_photo_id').val(attachment.id);
                $('#profile-photo-preview').html(
                    '<img src="' + attachment.url + '" style="width: 100px; height: 100px; object-fit: cover; border-radius: 50%;" alt="プロフィール画像">'
                );
                
                // 削除ボタンを表示
                if ($('#remove-profile-photo').length === 0) {
                    $('#upload-profile-photo').after('<button type="button" class="button" id="remove-profile-photo">画像を削除</button>');
                }
            });
            
            mediaUploader.open();
        });
        
        // 画像削除ボタンクリック(イベント委譲)
        $(document).on('click', '#remove-profile-photo', function(e) {
            e.preventDefault();
            
            $('#profile_photo_id').val('');
            $('#profile-photo-preview').html(
                '<div style="width: 100px; height: 100px; background-color: #f0f0f0; border-radius: 50%; display: flex; align-items: center; justify-content: center; color: #666;">画像なし</div>'
            );
            $(this).remove();
        });
    });
    </script>
    <?php
}

// ユーザープロフィール更新時の処理
add_action('personal_options_update', 'save_custom_profile_photo');
add_action('edit_user_profile_update', 'save_custom_profile_photo');

function save_custom_profile_photo($user_id) {
    if (!current_user_can('edit_user', $user_id)) {
        return false;
    }
    
    if (isset($_POST['profile_photo_id'])) {
        $profile_photo_id = sanitize_text_field($_POST['profile_photo_id']);
        
        if (empty($profile_photo_id)) {
            delete_user_meta($user_id, 'profile_photo_id');
        } else {
            update_user_meta($user_id, 'profile_photo_id', $profile_photo_id);
        }
    }
}

// アバター表示をカスタマイズ(Gravatarの代替)
add_filter('pre_get_avatar_data', 'custom_profile_photo_avatar', 10, 2);

function custom_profile_photo_avatar($args, $id_or_email) {
    $user = null;
    
    // ユーザーIDまたはメールからユーザー情報を取得
    if (is_numeric($id_or_email)) {
        $user = get_user_by('id', $id_or_email);
    } elseif (is_string($id_or_email)) {
        $user = get_user_by('email', $id_or_email);
    } elseif (is_object($id_or_email) && isset($id_or_email->user_id)) {
        $user = get_user_by('id', $id_or_email->user_id);
    }
    
    if (!$user) {
        return $args;
    }
    
    // カスタムプロフィール画像があるかチェック
    $profile_photo_id = get_user_meta($user->ID, 'profile_photo_id', true);
    
    if ($profile_photo_id) {
        $profile_photo_url = wp_get_attachment_url($profile_photo_id);
        
        if ($profile_photo_url) {
            $args['url'] = $profile_photo_url;
            $args['found_avatar'] = true;
        }
    }
    
    return $args;
}

// 管理画面でメディアライブラリのスクリプトを読み込み
add_action('admin_enqueue_scripts', 'enqueue_media_uploader_scripts');

function enqueue_media_uploader_scripts($hook) {
    if ($hook == 'profile.php' || $hook == 'user-edit.php') {
        wp_enqueue_media();
        wp_enqueue_script('jquery');
    }
}

// ユーザー一覧画面でカスタムプロフィール画像を表示
add_filter('get_avatar', 'show_custom_profile_photo_in_admin', 10, 5);

function show_custom_profile_photo_in_admin($avatar, $id_or_email, $size, $default, $alt) {
    $user = null;
    
    if (is_numeric($id_or_email)) {
        $user = get_user_by('id', $id_or_email);
    } elseif (is_string($id_or_email)) {
        $user = get_user_by('email', $id_or_email);
    }
    
    if (!$user) {
        return $avatar;
    }
    
    $profile_photo_id = get_user_meta($user->ID, 'profile_photo_id', true);
    
    if ($profile_photo_id) {
        $profile_photo_url = wp_get_attachment_url($profile_photo_id);
        
        if ($profile_photo_url) {
            $avatar = '<img alt="' . esc_attr($alt) . '" src="' . esc_url($profile_photo_url) . '" class="avatar avatar-' . esc_attr($size) . ' photo" height="' . esc_attr($size) . '" width="' . esc_attr($size) . '" />';
        }
    }
    
    return $avatar;
}

// プロフィール画像取得のヘルパー関数
function get_user_profile_photo($user_id, $size = 'thumbnail') {
    $profile_photo_id = get_user_meta($user_id, 'profile_photo_id', true);
    
    if ($profile_photo_id) {
        $image = wp_get_attachment_image_src($profile_photo_id, $size);
        if ($image) {
            return $image[0];
        }
    }
    
    return false;
}

// カスタムプロフィール画像があるかチェックする関数
function has_user_profile_photo($user_id) {
    $profile_photo_id = get_user_meta($user_id, 'profile_photo_id', true);
    return !empty($profile_photo_id);
}
2

管理画面の〈ユーザー〉→〈プロフィール画像設定〉でプロフィール画像を設定する

管理画面の〈ユーザー〉メニューで〈ユーザー一覧〉を開き、プロフィール画像を設定したいユーザーを選択します。
管理画面の配色やユーザ名などを設定するページ内に追加された〈プロフィール画像設定〉の項目から、お好きな画像を選択して設定してください。

設定後は意図したとおりにプロフィール画像が表示されているか、キャッシュを削除した上でご確認ください。

3
Note

《Gravatar》は〈メールアドレスに紐づいたアバター画像〉を世界中のWordPressサイトや多くのWebサービス共通利用するためのサービスです。
ユーザーは一度Gravatarで設定すれば、WordPressだけでなく他のGravatar対応サービスでも同じアイコンが使えます。各サイトごとに画像設定が必要になる手間を省き、ネット上における自身の顔(=アバター)を一元管理できるように設計されました。

仮にWordPress自体にGravatarと同様の機能を持たせようとすると、開発コストも管理コストも爆増してしまいます。そのためWordPressはアバター画像に関する全ての機能をGravatarに委託しているのです。

ですが管理コストなどが問題となるのは、あくまで〈グローバルに使えるアバター〉を求めた場合の話。自分のサイトだけで使うアイコンなら、堅牢なセキュリティ対策をほどこす必要はありません。
このカスタマイズはいわば〈自宅用のアバター〉をお求めの方向けです。およそでも使いたい方は、Gravatarのご利用をおすすめします。

補足:functions.phpに長々と記述したくない方向けのカスタマイズ

functions.phpの肥大化が気になる方は、以下の手順をご参照ください。

フォルダを準備

上記のコードを単独のphpファイルに記述し、functions.phpで呼び出すようにします。
まずは子テーマフォルダ直下にフォルダを1つ作成しましょう。
名前は任意、今回はincとします。

1

新規phpファイルにコードを記述

作成したincフォルダの中に、phpファイルを新規作成します。
名前は任意、今回はuser-profile-photo.phpとします。

user-profile-photo.php
<?php
// ================================
// カスタムプロフィール画像 機能
// ================================

// ユーザープロフィール画面にカスタムフィールドを追加
add_action('show_user_profile', 'add_custom_profile_photo_field');
add_action('edit_user_profile', 'add_custom_profile_photo_field');

function add_custom_profile_photo_field($user) {
    $profile_photo_id = get_user_meta($user->ID, 'profile_photo_id', true);
    $profile_photo_url = '';
    
    if ($profile_photo_id) {
        $profile_photo_url = wp_get_attachment_url($profile_photo_id);
    }
    ?>
    <h3>プロフィール画像設定</h3>
    <table class="form-table">
        <tr>
            <th><label for="profile_photo">アバター</label></th>
            <td>
                <div id="profile-photo-container">
                    <div id="profile-photo-preview" style="margin-bottom: 10px;">
                        <?php if ($profile_photo_url): ?>
                            <img src="<?php echo esc_url($profile_photo_url); ?>" 
                                 style="width: 100px; height: 100px; object-fit: cover; border-radius: 50%;" 
                                 alt="プロフィール画像">
                        <?php else: ?>
                            <div style="width: 100px; height: 100px; background-color: #f0f0f0; border-radius: 50%; display: flex; align-items: center; justify-content: center; color: #666;">
                                画像なし
                            </div>
                        <?php endif; ?>
                    </div>
                    <input type="hidden" id="profile_photo_id" name="profile_photo_id" value="<?php echo esc_attr($profile_photo_id); ?>">
                    <button type="button" class="button" id="upload-profile-photo">画像を選択</button>
                    <?php if ($profile_photo_id): ?>
                        <button type="button" class="button" id="remove-profile-photo">画像を削除</button>
                    <?php endif; ?>
                </div>
                <p class="description">
                    プロフィール画像を設定すると、Gravatarの代わりに使用されます。<br>
                    推奨サイズ: 150x150px以上の正方形画像
                </p>
            </td>
        </tr>
    </table>
    
    <script>
    jQuery(document).ready(function($) {
        var mediaUploader;
        
        // 画像選択ボタンクリック
        $('#upload-profile-photo').click(function(e) {
            e.preventDefault();
            
            if (mediaUploader) {
                mediaUploader.open();
                return;
            }
            
            mediaUploader = wp.media({
                title: 'プロフィール画像を選択',
                button: {
                    text: '画像を選択'
                },
                multiple: false,
                library: {
                    type: 'image'
                }
            });
            
            mediaUploader.on('select', function() {
                var attachment = mediaUploader.state().get('selection').first().toJSON();
                
                $('#profile_photo_id').val(attachment.id);
                $('#profile-photo-preview').html(
                    '<img src="' + attachment.url + '" style="width: 100px; height: 100px; object-fit: cover; border-radius: 50%;" alt="プロフィール画像">'
                );
                
                // 削除ボタンを表示
                if ($('#remove-profile-photo').length === 0) {
                    $('#upload-profile-photo').after('<button type="button" class="button" id="remove-profile-photo">画像を削除</button>');
                }
            });
            
            mediaUploader.open();
        });
        
        // 画像削除ボタンクリック(イベント委譲)
        $(document).on('click', '#remove-profile-photo', function(e) {
            e.preventDefault();
            
            $('#profile_photo_id').val('');
            $('#profile-photo-preview').html(
                '<div style="width: 100px; height: 100px; background-color: #f0f0f0; border-radius: 50%; display: flex; align-items: center; justify-content: center; color: #666;">画像なし</div>'
            );
            $(this).remove();
        });
    });
    </script>
    <?php
}

// ユーザープロフィール更新時の処理
add_action('personal_options_update', 'save_custom_profile_photo');
add_action('edit_user_profile_update', 'save_custom_profile_photo');

function save_custom_profile_photo($user_id) {
    if (!current_user_can('edit_user', $user_id)) {
        return false;
    }
    
    if (isset($_POST['profile_photo_id'])) {
        $profile_photo_id = sanitize_text_field($_POST['profile_photo_id']);
        
        if (empty($profile_photo_id)) {
            delete_user_meta($user_id, 'profile_photo_id');
        } else {
            update_user_meta($user_id, 'profile_photo_id', $profile_photo_id);
        }
    }
}

// アバター表示をカスタマイズ(Gravatarの代替)
add_filter('pre_get_avatar_data', 'custom_profile_photo_avatar', 10, 2);

function custom_profile_photo_avatar($args, $id_or_email) {
    $user = null;
    
    // ユーザーIDまたはメールからユーザー情報を取得
    if (is_numeric($id_or_email)) {
        $user = get_user_by('id', $id_or_email);
    } elseif (is_string($id_or_email)) {
        $user = get_user_by('email', $id_or_email);
    } elseif (is_object($id_or_email) && isset($id_or_email->user_id)) {
        $user = get_user_by('id', $id_or_email->user_id);
    }
    
    if (!$user) {
        return $args;
    }
    
    // カスタムプロフィール画像があるかチェック
    $profile_photo_id = get_user_meta($user->ID, 'profile_photo_id', true);
    
    if ($profile_photo_id) {
        $profile_photo_url = wp_get_attachment_url($profile_photo_id);
        
        if ($profile_photo_url) {
            $args['url'] = $profile_photo_url;
            $args['found_avatar'] = true;
        }
    }
    
    return $args;
}

// 管理画面でメディアライブラリのスクリプトを読み込み
add_action('admin_enqueue_scripts', 'enqueue_media_uploader_scripts');

function enqueue_media_uploader_scripts($hook) {
    if ($hook == 'profile.php' || $hook == 'user-edit.php') {
        wp_enqueue_media();
        wp_enqueue_script('jquery');
    }
}

// ユーザー一覧画面でカスタムプロフィール画像を表示
add_filter('get_avatar', 'show_custom_profile_photo_in_admin', 10, 5);

function show_custom_profile_photo_in_admin($avatar, $id_or_email, $size, $default, $alt) {
    $user = null;
    
    if (is_numeric($id_or_email)) {
        $user = get_user_by('id', $id_or_email);
    } elseif (is_string($id_or_email)) {
        $user = get_user_by('email', $id_or_email);
    }
    
    if (!$user) {
        return $avatar;
    }
    
    $profile_photo_id = get_user_meta($user->ID, 'profile_photo_id', true);
    
    if ($profile_photo_id) {
        $profile_photo_url = wp_get_attachment_url($profile_photo_id);
        
        if ($profile_photo_url) {
            $avatar = '<img alt="' . esc_attr($alt) . '" src="' . esc_url($profile_photo_url) . '" class="avatar avatar-' . esc_attr($size) . ' photo" height="' . esc_attr($size) . '" width="' . esc_attr($size) . '" />';
        }
    }
    
    return $avatar;
}

// プロフィール画像取得のヘルパー関数
function get_user_profile_photo($user_id, $size = 'thumbnail') {
    $profile_photo_id = get_user_meta($user_id, 'profile_photo_id', true);
    
    if ($profile_photo_id) {
        $image = wp_get_attachment_image_src($profile_photo_id, $size);
        if ($image) {
            return $image[0];
        }
    }
    
    return false;
}

// カスタムプロフィール画像があるかチェックする関数
function has_user_profile_photo($user_id) {
    $profile_photo_id = get_user_meta($user_id, 'profile_photo_id', true);
    return !empty($profile_photo_id);
}
Note

コード内容自体はfunctions.phpに追加する場合と全く同じですが、冒頭の<?phpを忘れないようご注意ください。

2

functions.phpにコードを追加する

functions.phpに下記のコードを追加します。

functions.php
//プロフィール画像設定:呼び出し
require_once get_stylesheet_directory() . '/inc/user-profile-photo.php';
Note

フォルダ名やファイル名を変更した場合は、コード内のパスを修正してください。

3

動作確認

正常に機能することを確認してください。

4

コメント

※送信されたコメントは管理者が確認するまで表示されません。