2026年8月8日
2026年8月8日
WordPressのユーザープロフィールにカスタムフィールドを追加する方法
はじめに
WordPressのユーザープロフィールは標準フィールドだけでは不十分なことが多く、プロフィール写真のURL、SNSアカウント、所属部署などの情報を追加したいケースが頻繁にあります。show_user_profileとedit_user_profileアクションを使えば、管理画面のプロフィールページに独自フィールドを安全に追加・保存できます。
症状・原因
- ユーザープロフィールに所属・肩書きなどの独自情報を追加できない
- SNSのプロフィールリンクをデフォルトの「ウェブサイト」欄以外に追加したい
- フロントエンドのプロフィールページでカスタム情報を表示したい
- ユーザーごとに独自のアバター画像URLを設定させたい
user_contactmethodsが何なのか分からずSNSリンクの追加方法が不明
解決手順
ステップ1:show_user_profile/edit_user_profileでフィールドを追加
<?php
/**
* 管理画面のプロフィールページにカスタムフィールドを追加
*
* show_user_profile:自分のプロフィール編集時
* edit_user_profile:管理者が他ユーザーを編集する時
* 両方にフックすることで全ケースに対応
*/
function add_custom_user_profile_fields( $user ) {
// カスタムフィールドの値を取得
$company = get_user_meta( $user->ID, 'company', true );
$department = get_user_meta( $user->ID, 'department', true );
$position = get_user_meta( $user->ID, 'position', true );
$phone = get_user_meta( $user->ID, 'phone', true );
$bio_short = get_user_meta( $user->ID, 'bio_short', true );
?>
<!-- nonceフィールドでセキュリティ確保 -->
<?php wp_nonce_field( 'save_custom_user_profile', 'custom_profile_nonce' ); ?>
<h2>追加プロフィール情報</h2>
<table class="form-table" role="presentation">
<tr>
<th scope="row">
<label for="company">会社・組織名</label>
</th>
<td>
<input type="text" name="company" id="company"
value="<?php echo esc_attr( $company ); ?>"
class="regular-text" />
</td>
</tr>
<tr>
<th scope="row">
<label for="department">部署名</label>
</th>
<td>
<input type="text" name="department" id="department"
value="<?php echo esc_attr( $department ); ?>"
class="regular-text" />
</td>
</tr>
<tr>
<th scope="row">
<label for="position">役職・肩書き</label>
</th>
<td>
<input type="text" name="position" id="position"
value="<?php echo esc_attr( $position ); ?>"
class="regular-text" />
</td>
</tr>
<tr>
<th scope="row">
<label for="phone">電話番号</label>
</th>
<td>
<input type="tel" name="phone" id="phone"
value="<?php echo esc_attr( $phone ); ?>"
class="regular-text" />
<p class="description">公開されません。管理者のみ閲覧可能です。</p>
</td>
</tr>
<tr>
<th scope="row">
<label for="bio_short">一言自己紹介</label>
</th>
<td>
<textarea name="bio_short" id="bio_short" rows="3"
class="large-text"><?php echo esc_textarea( $bio_short ); ?></textarea>
<p class="description">120文字以内で入力してください。</p>
</td>
</tr>
</table>
<?php
}
// 自分のプロフィール + 他ユーザーのプロフィール両方にフック
add_action( 'show_user_profile', 'add_custom_user_profile_fields' );
add_action( 'edit_user_profile', 'add_custom_user_profile_fields' );
?>
ステップ2:personal_options_update/edit_user_profile_updateで保存処理
<?php
/**
* カスタムプロフィールフィールドの保存処理
*
* personal_options_update:自分のプロフィール更新時
* edit_user_profile_update:管理者が他ユーザーを更新する時
*/
function save_custom_user_profile_fields( $user_id ) {
// nonceの検証(セキュリティチェック)
if ( ! isset( $_POST['custom_profile_nonce'] ) ||
! wp_verify_nonce( $_POST['custom_profile_nonce'], 'save_custom_user_profile' ) ) {
return;
}
// 権限チェック:自分のプロフィールか管理者のみ保存可能
if ( ! current_user_can( 'edit_user', $user_id ) ) {
return;
}
// 保存するフィールドのリスト(サニタイズ方法も定義)
$fields_to_save = array(
'company' => 'sanitize_text_field',
'department' => 'sanitize_text_field',
'position' => 'sanitize_text_field',
'phone' => 'sanitize_text_field',
'bio_short' => 'sanitize_textarea_field',
);
foreach ( $fields_to_save as $field_key => $sanitize_function ) {
if ( isset( $_POST[ $field_key ] ) ) {
// サニタイズしてからuser_metaに保存
$value = call_user_func( $sanitize_function, $_POST[ $field_key ] );
// bio_shortは文字数制限
if ( 'bio_short' === $field_key && mb_strlen( $value ) > 120 ) {
$value = mb_substr( $value, 0, 120 );
}
update_user_meta( $user_id, $field_key, $value );
}
}
// 保存成功の管理画面通知
add_filter( 'user_profile_update_errors', function( $errors ) {
// エラーがない場合のみ成功メッセージを追加
if ( ! $errors->get_error_codes() ) {
// 成功通知はWordPressがデフォルトで表示する
}
} );
}
add_action( 'personal_options_update', 'save_custom_user_profile_fields' );
add_action( 'edit_user_profile_update', 'save_custom_user_profile_fields' );
?>
ステップ3:フロントエンドテンプレートでuser_metaを表示
<?php
/**
* フロントエンドのプロフィールページでカスタムフィールドを表示
* author.php や page-profile.php で使用
*/
function render_user_profile( $user_id = null ) {
// user_idが指定されない場合は現在のアーカイブユーザーを使用
if ( null === $user_id ) {
$user = get_queried_object();
$user_id = $user->ID ?? 0;
}
if ( ! $user_id ) return;
// ユーザー情報を取得
$user = get_userdata( $user_id );
$company = get_user_meta( $user_id, 'company', true );
$department = get_user_meta( $user_id, 'department', true );
$position = get_user_meta( $user_id, 'position', true );
$bio_short = get_user_meta( $user_id, 'bio_short', true );
// SNSリンク(ステップ5で追加したフィールド)
$twitter = get_user_meta( $user_id, 'twitter', true );
$linkedin = get_user_meta( $user_id, 'linkedin', true );
?>
<div class="author-profile">
<!-- アバター(カスタムURLまたはGravatar) -->
<div class="author-avatar">
<?php echo get_avatar( $user_id, 120, '', '', array( 'class' => 'author-photo' ) ); ?>
</div>
<!-- 著者情報 -->
<div class="author-info">
<h1 class="author-name"><?php echo esc_html( $user->display_name ); ?></h1>
<?php if ( $position || $company ) : ?>
<p class="author-title">
<?php echo esc_html( $position ); ?>
<?php if ( $position && $company ) echo ' / '; ?>
<?php echo esc_html( $company ); ?>
<?php if ( $department ) echo ' ' . esc_html( $department ); ?>
</p>
<?php endif; ?>
<?php if ( $bio_short ) : ?>
<p class="author-bio-short"><?php echo esc_html( $bio_short ); ?></p>
<?php endif; ?>
<?php if ( $user->user_description ) : ?>
<div class="author-bio"><?php echo wpautop( esc_html( $user->user_description ) ); ?></div>
<?php endif; ?>
<!-- SNSリンク -->
<div class="author-social">
<?php if ( $twitter ) : ?>
<a href="https://twitter.com/<?php echo esc_attr( ltrim( $twitter, '@' ) ); ?>"
class="social-link twitter" target="_blank" rel="noopener noreferrer">
Twitter
</a>
<?php endif; ?>
<?php if ( $linkedin ) : ?>
<a href="<?php echo esc_url( $linkedin ); ?>"
class="social-link linkedin" target="_blank" rel="noopener noreferrer">
LinkedIn
</a>
<?php endif; ?>
</div>
</div>
</div>
<?php
}
?>
ステップ4:get_avatar_urlフィルターでカスタムアバターURLを設定
<?php
/**
* カスタムアバターURL機能の実装
* ユーザーが自分のアバター画像URLを設定できるようにする
*/
// --- プロフィール画面にアバターURLフィールドを追加 ---
function add_avatar_url_field( $user ) {
$avatar_url = get_user_meta( $user->ID, 'custom_avatar_url', true );
?>
<h2>カスタムアバター</h2>
<table class="form-table">
<tr>
<th><label for="custom_avatar_url">アバター画像URL</label></th>
<td>
<input type="url" name="custom_avatar_url" id="custom_avatar_url"
value="<?php echo esc_url( $avatar_url ); ?>"
class="regular-text" />
<p class="description">
GravatarのかわりにカスタムURLの画像をアバターとして使用します。<br>
推奨サイズ:200×200px以上の正方形画像
</p>
<?php if ( $avatar_url ) : ?>
<div class="avatar-preview">
<img src="<?php echo esc_url( $avatar_url ); ?>"
alt="アバタープレビュー" width="80" height="80"
style="border-radius:50%;margin-top:8px;" />
</div>
<?php endif; ?>
</td>
</tr>
</table>
<?php
}
add_action( 'show_user_profile', 'add_avatar_url_field' );
add_action( 'edit_user_profile', 'add_avatar_url_field' );
// --- アバターURL保存処理 ---
function save_avatar_url( $user_id ) {
if ( ! current_user_can( 'edit_user', $user_id ) ) return;
if ( isset( $_POST['custom_avatar_url'] ) ) {
$url = esc_url_raw( $_POST['custom_avatar_url'] );
// URLが画像ファイルかどうかを簡易チェック
if ( empty( $url ) || preg_match( '/\.(jpg|jpeg|png|gif|webp)(\?.*)?$/i', $url ) ) {
update_user_meta( $user_id, 'custom_avatar_url', $url );
}
}
}
add_action( 'personal_options_update', 'save_avatar_url' );
add_action( 'edit_user_profile_update', 'save_avatar_url' );
// --- get_avatar_urlフィルターでカスタムURLを優先使用 ---
function use_custom_avatar_url( $url, $id_or_email, $args ) {
$user_id = 0;
// $id_or_email からユーザーIDを取得
if ( is_numeric( $id_or_email ) ) {
$user_id = (int) $id_or_email;
} elseif ( is_string( $id_or_email ) ) {
$user = get_user_by( 'email', $id_or_email );
if ( $user ) $user_id = $user->ID;
} elseif ( $id_or_email instanceof WP_User ) {
$user_id = $id_or_email->ID;
}
if ( $user_id > 0 ) {
$custom_url = get_user_meta( $user_id, 'custom_avatar_url', true );
if ( ! empty( $custom_url ) ) {
return $custom_url; // カスタムURLをGravatarの代わりに使用
}
}
return $url; // カスタムURLがなければデフォルトのGravatarを使用
}
add_filter( 'get_avatar_url', 'use_custom_avatar_url', 10, 3 );
?>
ステップ5:user_contactmethodsフィルターでSNSリンクを追加
<?php
/**
* ユーザープロフィールのコンタクト方法にSNSリンクを追加
* user_contactmethods フィルターで管理
*
* デフォルトではWordPressはコンタクトフィールドを持たない(旧バージョンはMySpaceなど)
*/
function add_social_media_contacts( $methods ) {
// 不要なデフォルトフィールドを削除(任意)
unset( $methods['aim'] ); // 旧AOL Instant Messenger
unset( $methods['jabber'] ); // 旧Jabber
unset( $methods['yim'] ); // 旧Yahoo Messenger
// SNSリンクを追加
$methods['twitter'] = 'Twitter / X ユーザー名(@なし)';
$methods['facebook'] = 'Facebook プロフィールURL';
$methods['instagram'] = 'Instagram ユーザー名';
$methods['linkedin'] = 'LinkedIn プロフィールURL';
$methods['youtube'] = 'YouTube チャンネルURL';
$methods['github'] = 'GitHub ユーザー名';
return $methods;
}
add_filter( 'user_contactmethods', 'add_social_media_contacts' );
/**
* フロントエンドでSNSリンクを表示するヘルパー関数
* author.php から呼び出し
*/
function get_user_social_links( $user_id ) {
$social_links = array();
// user_contactmethods で登録したキーでメタを取得
$twitter = get_the_author_meta( 'twitter', $user_id );
$facebook = get_the_author_meta( 'facebook', $user_id );
$instagram = get_the_author_meta( 'instagram', $user_id );
$linkedin = get_the_author_meta( 'linkedin', $user_id );
$github = get_the_author_meta( 'github', $user_id );
// URLを整形
if ( $twitter ) $social_links['twitter'] = 'https://twitter.com/' . ltrim( $twitter, '@' );
if ( $facebook ) $social_links['facebook'] = esc_url( $facebook );
if ( $instagram ) $social_links['instagram'] = 'https://instagram.com/' . ltrim( $instagram, '@' );
if ( $linkedin ) $social_links['linkedin'] = esc_url( $linkedin );
if ( $github ) $social_links['github'] = 'https://github.com/' . ltrim( $github, '@' );
return $social_links;
}
?>
注意事項
- nonce検証: プロフィールフィールドの保存には
wp_nonce_field()とwp_verify_nonce()を必ず組み合わせてCSRF攻撃を防止してください - 権限チェック:
current_user_can( 'edit_user', $user_id )で権限を確認してから保存処理を実行してください - サニタイズ: テキストフィールドは
sanitize_text_field()、URLはesc_url_raw()、テキストエリアはsanitize_textarea_field()でそれぞれサニタイズしてください get_the_author_meta:user_contactmethodsで追加したフィールドはget_the_author_meta()でも取得できます
まとめ
show_user_profile/edit_user_profileでフィールドを表示、personal_options_update/edit_user_profile_updateで保存、get_avatar_urlフィルターでカスタムアバター、user_contactmethodsでSNSリンクを追加することで、WordPressのユーザープロフィールを大幅に拡張できます。関連記事:WordPressのユーザー登録フォームをカスタマイズしてセキュリティを強化する方法