The essence of plugins is giving to WordPress users more control over their blog, that is, most of the time, more options. Typically, a plugin adds a page under the Settings menu, where you can modify the options (see this article on register_setting() for best practices).
But if you think about multi user blogs, it can make sense to implement per user options instead of "global" settings. And guess what? It's dead easy.
First, a few theory, then a complete example. Scroll down if you're the kind of guy who likes code, not explanations :)
Modify the "Profile" page
What we are going to do is play with the action hooks provided by file wp-admin/user-edit.php to add some fields to the profile page, then save them.
To add content (ie fields, checkboxes, texareas...) to the profile page, you can use any of the 3 actions:
- personal_options: append content to the "Personal Options" block
- profile_personal_options: add content after the "Personal Options" block (like add a whole new custom block)
- show_user_profile: add content right before the "Update Profile" button
For instance, to add content within the "Personal Options" block, you simply need to do something like:
-
add_action('personal_options', 'ozh_personal_options');
-
function ozh_personal_options() {
-
echo "<p>Content added by action 'personal_options'</p>";
-
}
These action hooks will pass one parameter to your function (that is ozh_personal_options() in the above example) containing a WP_user object.
Save custom per user data
Simply adding fields and pressing "Update Profile" won't do, you need to tell WordPress what you want to save. Hook into action personal_options_update and sanitize, I mean, SANITIZE, the POSTed data. This action will pass the user ID as a parameter to your custom function. Example:
-
add_action('personal_options_update', 'ozh_save_user_setting');
-
function ozh_save_user_setting( $user_id ) {
-
$option = ( $_post['somecheckbox'] == 'yes' ? 'yes' : 'no' ); // sanitize: accept only 'yes' or 'no'
-
update_usermeta( $user_id, 'some_user_options', $option );
-
}
Complete example of a plugin with per user setting
Let's make a dummy plugin that will allow registered users of a blog to be nagged by a silly javascript alert box on every admin page they'll visit.
-
<?php
-
/*
-
Plugin Name: Example plugin - Per User Settings
-
Plugin URI: http://planetozh.com/blog/
-
Description: Add a silly per user setting to your <a href="profile.php">Profile</a> page
-
Author: Ozh
-
Author URI: http://planetozh.com/
-
*/
-
-
// Add a custom field to the form in "Profile"
-
function ozh_user_setting_alert_box($user) {
-
?>
-
<tr>
-
<th scope="row">Add Alert Box</th>
-
<td><label for="ozh_add_nag">
-
<input name="ozh_add_nag" type="checkbox" id="ozh_add_nag" value="1" <?php checked('1', $user->ozh_add_nag); ?> /> Add a silly and annoying alert box on each admin page
-
</label></td>
-
</tr>
-
<?php
-
}
-
-
// Handle data that's posted and sanitize before saving it
-
function ozh_save_user_setting_alert_box( $user_id ) {
-
$ozh_add_nag = ( !empty($_POST['ozh_add_nag']) ? 1 : 0 );
-
update_usermeta( $user_id, 'ozh_add_nag', $ozh_add_nag );
-
}
-
-
// Now, the per user behavior itself: add the silly alert box if applicable
-
function ozh_get_user_setting_alert_box() {
-
if( get_user_option('ozh_add_nag') ) {
-
?>
-
<script type="text/javascript">
-
alert("Annoying, isn't it?");
-
</script>
-
<?php
-
}
-
}
-
-
// Hook everything
-
add_action('personal_options', 'ozh_user_setting_alert_box');
-
add_action('personal_options_update', 'ozh_save_user_setting_alert_box');
-
add_action('admin_head', 'ozh_get_user_setting_alert_box');
-
-
?>
For your convenience, the above plugin example and a few more inline comments is available here (rename as .php)
Best practices
A few things you'll want to do:
- Visual integration: use the same markup and CSS classes than the latest WordPress as of date to add rows and fields. Your plugin must add content to the profile page as if it was a built-in option. I hate it when plugin options look like weird plugin option. It must look like WordPress.
- Data sanitization: don't save blindly and assume everything posted will be stupid or malicious. If you're expecting an integer, use intval(). If you're expecting one value from a set, explicitely test for each value. If you're expecting free text including HTML, use esc_html(). And so on. Sanitize everything.
- Data concatenation: if you're going to add several options, please, put them in one array and save only this one entry.
- Wise implementation: sometimes it just makes sense to have a standalone plugin option page with global settings instead of per user settings. The typical WordPress blog is a single user blog.
Related posts
Shorter URL
Want to share or tweet this post? Please use this short URL: http://ozh.in/rq
thought, on 28/Jan/10 at 6:13 am # :
Thanks for this great article..
thought, on 05/Feb/10 at 2:57 am # :
There's a fourth place on the Profile screen where you can add fields.
By filtering 'user_contactmethods' you can quickly add a text input field to the Contact Info section. You can also use the filter to remove or rename the existing fields if so inclined.
Here's some example code:
function my_user_contactmethods($methods){
$methods['phone'] = 'Phone Number';
return $methods;
}
add_filter('user_contactmethods','my_user_contactmethods');
The above code will add a 'Phone Number' text input to the Contact Info section.
Note that you still have to include the code to manually update the user meta when the form is submitted, as in Ozh' examples.