How Can I Create WordPress User Profiles with Frontend Editing and Custom User Fields?
In this post, we'll create custom WordPress user profiles that users can update from the frontend of your site.
We'll be using a well-maintained WordPress plugin called Theme My Login (TML) that gives you a head start on creating custom login pages and front-end user profile editing. It's got filters and action hooks so it's extensible and you can easily take their default templates and make them your own. It's also got settings that let you hide the WordPress dashboard from regular users, send custom emails to new users, and more. Then we'll combine TML with Advanced Custom Fields (ACF) user fields to create a custom user experience.
First up, use ACF to make a field group with rules to display if "current user role is equal to admin" and "current user is equal to viewing backend" and "user form is equal to all". This will create a field group that is accessible to administrators viewing Users in the WordPress backend. The fields will still be accessible to your front-end users but we'll be adding the fields to our login and profile page templates ourselves so we have more control. (The other option is to let ACF display the fields automatically via the "register-form" and "show_user_profile" hooks in your templates.)
Next, add your custom fields to the field group you just created. This could be anything from a shipping address to a preferred method of contact — any additional information that you want to gather from your users. Also keep in mind that you can choose which fields the users themselves will have access to on the registration and profile templates so you could create fields that are only viewable by yourself and other admin users.
Now add the new fields to your user profile and registration forms for users to access via the frontend of your site. TML knows to look for customized templates in your active theme directory before going to the default templates that come with the plugin. So all you need to do is copy the templates you want to customize from the plugin directory into your theme folder and edit them there. To add the new fields, follow the structure of the the existing fields making sure to update the name, id and value attributes to match your new field name. You can add headers and subheaders and do whatever you need to create the user experience you want — as long as you edit the templates in your theme directory, they won't be overwritten when you update the plugin.
Lastly, the fields you added to your templates need to be saved when a user submits the form. To do this, we'll add a couple functions for TML to run on the appropriate action hooks. TML knows to look for a file called theme-my-login-custom.php in the plugins directory. Create this file and make sure to save it to the wp-content/plugins directory — if you were to put it inside the theme-my-login directory, it would get overwritten next time you update.
If you need custom validation on your new fields, add them to a filter like this:
function tml_registration_errors( $errors ) {
if ( empty( $_POST['user_street_address_1'] ) )
$errors->add( 'empty_user_street_address_1', '<strong>ERROR</strong>: Please enter a street address.' );
return $errors;
}
add_filter( 'registration_errors', 'tml_registration_errors' );
Now add your custom fields to the actions that will save your user data when they register or update their profile:
function tml_user_register( $user_id ) {
if ( !empty( $_POST['user_street_address_1'] ) )
update_user_meta( $user_id, 'user_street_address_1', $_POST['user_street_address_1'] );
if ( !empty( $_POST['user_street_address_2'] ) )
update_user_meta( $user_id, 'user_street_address_2', $_POST['user_street_address_2'] );
}
add_action( 'user_register', 'tml_user_register' );
function tml_user_update( $user_id ) {
// this is a required field
if ( !empty( $_POST['user_street_address_1'] ) )
update_user_meta( $user_id, 'user_street_address_1', $_POST['user_street_address_1'] );
// this field is optional
if ( !empty( $_POST['user_street_address_2'] ) ) :
update_user_meta( $user_id, 'user_street_address_2', $_POST['user_street_address_2'] );
else :
// delete the user meta if the field is empty
delete_user_meta( $user_id, 'user_street_address_2' );
endif;
}
add_action( 'profile_update', 'tml_user_update' );
In case you're wondering about security (and you should be!)... it's an important security practice to sanitize your data whenever you're saving input from users. Because we're using the update_user_meta() function, WordPress is sanitizing our data for us. For a good overview of data sanitization practices in WordPress, see this tuts+ blog post about sanitization.
You should now be able to test your forms and make sure they're behaving as intended. If something isn't saving or updating, double check that the input names in your templates match the ACF fields they're associated with.