How to add extra fields in user editing with PHP in WordPress

Contents

Overview

This article is a complete, practical, copy-paste ready guide to adding extra fields to WordPress user editing screens (both admin profile edit and front-end registration) using PHP. It covers:

  • How to display fields on the profile and new-user pages
  • How to validate and save submitted values securely
  • How to add fields to front-end registration and validate them
  • Example field types: text, textarea, checkbox, select and file upload (avatar)
  • How to expose user meta through the REST API
  • Best practices and common pitfalls

Principles and WordPress hooks used

Do not alter core database tables. Use user meta (get_user_meta / update_user_meta). Use the profile display hooks to inject form fields and the save hooks to persist them. Always sanitize input, escape output, and verify nonces and capabilities.

  • Display profile fields (admin): show_user_profile, edit_user_profile
  • Save profile fields (admin): personal_options_update, edit_user_profile_update
  • Display new-user form (admin): user_new_form
  • Register front-end fields: register_form
  • Validate front-end registration: registration_errors
  • Save on registration or any new user creation: user_register
  • Validate admin-created users: user_profile_update_errors
  • Expose meta in REST: register_meta / register_rest_field

Minimal working example (text field) — Admin profile save

This example shows a simple phone number field added to the admin profile page and saved to user meta. It demonstrates nonce usage, capability check, proper sanitization and escaping.

ID, uef_phone, true)
    ?>
    

class=regular-text />

What this does and why

  • show_user_profile and edit_user_profile are used to render the field for the current user and when an admin edits another user.
  • personal_options_update and edit_user_profile_update save the data on profile submission.
  • wp_nonce_field wp_verify_nonce protect against CSRF.
  • current_user_can(edit_user, user_id) prevents unauthorized updates.
  • sanitize_text_field stores clean text and esc_attr is used for safe output.

Front-end registration: add field, validate, save

If you need the same field on the regular registration form, hook into register_form, registration_errors and user_register. Below is a complete example for adding the phone field to the front-end registration, validating it and saving it.


    

add(uef_phone_error, __(ERROR: Please enter a phone number.)) } else { phone = sanitize_text_field(_POST[uef_phone]) // Example simple validation (adjust pattern to your needs) if ( strlen(phone) < 6 ) { errors->add(uef_phone_error_short, __(ERROR: Phone number too short.)) } } return errors } // Save phone after user is created add_action(user_register, uef_user_register) function uef_user_register(user_id) { if (isset(_POST[uef_phone])) { update_user_meta(user_id, uef_phone, sanitize_text_field(_POST[uef_phone])) } } ?>

Admin new-user form

To display custom fields when an admin creates a user in wp-admin (Users rarr Add New), hook user_new_form and validate with user_profile_update_errors. Save using user_register.


    

user_login contains submitted login if ( ! update ) { if ( empty( _POST[uef_phone] ) ) { errors->add(uef_phone_error, __(ERROR: Please enter a phone number.)) } } } ?>

Advanced example: checkbox, select, textarea, and file upload (avatar)

This section provides snippets for different form controls and a file upload handled via the WordPress media API to associate an attachment ID with user meta.

Checkbox and select rendering saving

ID, uef_agree_terms, true)
    color = get_user_meta(user->ID, uef_fav_color, true)
    ?>
    
/>

File upload (use WordPress Media API) — example

File uploads must use the WordPress admin media handling functions. On profile pages in wp-admin, file uploads are allowed. The example below saves the attachment ID in user meta.

ID, uef_avatar_id, true)
    ?>
    


Expose user meta in the REST API

To include your custom user meta on REST requests (wp/v2/users or wp/v2/users/), register the meta with show_in_rest true or register a rest field.

 string,
        single => true,
        show_in_rest => true,
        auth_callback => function() { return current_user_can(list_users) } // adjust capability
    ))
}
?>

Alternatively, use register_rest_field if you want a custom getter and schema.

Best practices and security checklist

  • Prefix meta keys: Use a unique prefix (eg. uef_ or myplugin_user_). Prevent name collisions.
  • Sanitize on input: sanitize_text_field, sanitize_email, esc_url_raw, wp_strip_all_tags, intval, floatval as appropriate.
  • Escape on output: esc_attr, esc_html, esc_url when rendering fields.
  • Nonce protection: Use wp_nonce_field in forms and wp_verify_nonce on save.
  • Capability checks: current_user_can(edit_user, user_id) before saving admin edits.
  • Validation: Use registration_errors and user_profile_update_errors to add errors that are shown to the user when appropriate.
  • Use WordPress APIs for files: media_handle_upload and related functions to ensure files are processed safely.
  • REST exposure: register_meta with show_in_rest and an appropriate auth_callback to avoid leaking private data.
  • Localization: Wrap user-visible strings with translation functions when converting this into a production plugin (e.g. __()).

Multisite notes and capabilities

In multisite, user capability flow can vary. Check current_user_can(create_users) for network-level creation or map meta visibility carefully. Be aware of where a users profile edit screen appears (network admin vs site user edit). If your field is sensitive, restrict REST exposure and who can read it.

Troubleshooting and FAQs

  1. Form value not saved
    Ensure your save hook runs (personal_options_update / edit_user_profile_update). For new users created via admin, use user_register for saving, and user_profile_update_errors for validation.
  2. Files failing to upload
    Ensure you included the required files: wp-admin/includes/file.php, media.php, image.php before calling media_handle_upload. Also check PHP upload limits and file permissions.
  3. Value not visible via REST
    Use register_meta(user, meta_key, array(show_in_rest => true, …)) during init.
  4. Nonce failing
    Nonce fields must be printed on the same page and verified on the same request. Ensure the field name used in wp_nonce_field matches the name you verify.

Hook quick reference

Hook When to use
show_user_profile / edit_user_profile Render profile fields in admin (own profile and edit other users)
personal_options_update / edit_user_profile_update Save profile fields from admin profile form
user_new_form Render fields on admin Add New User screen
user_profile_update_errors Validate admin-created users
register_form Add fields to front-end registration form
registration_errors Validate front-end registration
user_register Save data when a user is created (admin or front-end)
register_meta Expose user meta to REST API safely

Full production-ready plugin example (complete)

The following is a consolidated, production-ready plugin file that demonstrates multiple field types, proper sanitization, nonce protection, REST registration (phone), admin and front-end handling, plus avatar upload. You can save this as a single PHP file inside wp-content/plugins/ and activate it for testing. Adjust strings, validation and meta keys to fit your needs.

ID, uef_phone, true)
    bio   = get_user_meta(user->ID, uef_bio, true)
    agree = get_user_meta(user->ID, uef_agree_terms, true)
    color = get_user_meta(user->ID, uef_fav_color, true)
    avatar_id = get_user_meta(user->ID, uef_avatar_id, true)
    ?>
    

class=regular-text />
/>

add(uef_phone_error, __(ERROR: Please enter a phone number.)) } else { phone = sanitize_text_field(_POST[uef_phone]) if ( strlen(phone) < 6 ) { errors->add(uef_phone_error_short, __(ERROR: Phone number too short.)) } } return errors } add_action(user_register, uef_user_register_save) function uef_user_register_save(user_id) { if (isset(_POST[uef_phone])) { update_user_meta(user_id, uef_phone, sanitize_text_field(_POST[uef_phone])) } } // ---------- Register meta for REST ---------- add_action(init, uef_register_meta_for_rest) function uef_register_meta_for_rest() { register_meta(user, uef_phone, array( type => string, single => true, show_in_rest => true, sanitize_callback => sanitize_text_field, auth_callback => function() { // Only allow authenticated users to see user meta via REST in this example return is_user_logged_in() }, )) } ?>

Extra tips

  • When adding many fields or grouping fields, consider using a settings page for configuration and keep user meta keys consistent.
  • Use nonces with unique names if you have multiple forms on a page so verification distinguishes them.
  • If you need complex validation, move that logic into separate functions to keep hooks concise.
  • If other plugins/themes need access to these fields, document the meta keys and preferred data types.
  • When using media_handle_upload, remember attachments are stored in the global media library. Clean-up attachments if users are deleted, if required, to avoid orphan files.

Resources



Acepto donaciones de BAT's mediante el navegador Brave 🙂



Leave a Reply

Your email address will not be published. Required fields are marked *