[wp-hackers] Settings API: Showing errors if validation fails
Jeremy Clarke
jer at simianuprising.com
Wed Dec 16 23:23:32 UTC 2009
After the recent discussion about the Settings API and before I added a
bunch of settings to my custom plugin I decided to follow Otto's tutorial
and set up my options page using registered settings, settings sections and
settings fields. (
http://ottodestruct.com/blog/2009/wordpress-settings-api-tutorial/)
It took a while but I got it all working and overall I'm really happy with
how the system works and cleans up my incredibly messy code.
That said I can't find any way to show users errors when they give invalid
input.
When you register_setting() your setting (which is probably an array of
options, you run register_settings() once for each wp_options entry), you
give it a validation callback function.
This function gives you $input which is the $_POST value for your option and
you return the value you want saved to the db. It actually runs as a filter
during update_option(), which is what gets run on all the Settings API stuff
when you save the page. The idea is you filter/sanitize etc the data in the
function and only return what is good.
This works great if what you want to do is either a) return correct input or
b) return absolutely nothing, but leaves you stranded if you want to help
your users correct their mistake. In fact no matter what happens with the
validation the user sees "Settings Saved" at the top of the screen after
submitting a form. This is super bad usability and could easily lead to lots
of users thinking their data was saved when in fact it wasn't.
As a perfect example of the defect try changing the admin email setting in a
WP install to something without an @ sign (a validation error). The result
is 'Settings Saved' at the top and an empty admin email field. Needless to
say, this is a nightmare for so many reasons.
So my question: Has anyone found a way around this issue on their own? As
far as I can tell there is no built in way to handle it, but maybe someone
has a hack we can use till it gets solved in core? Preferably something that
takes less code than going back to not using the Settings API?
Part of the problem is that the processing and validation happen on a
different execution from the pageload the user ends up on, during the load
of /wp-admin/options.php, which is what you target your <form> at when using
the Settings API. Once the Settings API has finished its saving/validation
it does this:
$goback = add_query_arg( 'updated', 'true', wp_get_referer() );
wp_redirect( $goback );
So there is pretty much no way to send back data about the validation error.
In #wordpress-dev Mark Jaquith recommended doing
wp_redirect( $your_plugin_admin_url . '&mypluginerrorid=1' );
exit();
when there is a validation error. But that would mean giving up on any other
values in the same registered setting (none of it would be saved), as well
as any other setting sections/fields that hadn't been processed yet during
that form submission.
Any ideas?
In terms of building out core to take care of it I think the solution is a
function that can be called during an options validation that saves a value
which gets added to the wp_redirect() before it gets sent back. I.e. in
options.php instead of just adding 'updated', 'true' it would first check
for an alternate message and use that instead. Something like:
add_settings_error("Sorry, what you entered for Admin Email is
definitely not an email. Maybe an @ would be nice?");
Then something like get_settings_error() to fill the add_query_var() before
redirection.
You could also create a $error_msg variable in your validation function and
just add new text to it as you go along validating different values. This
way you could also put good news in there like "Email saved, subscription
preferences saved" etc.
Without any error messaging about validation the Settings API is pretty
crippled, almost to the point of being useless compared to processing the
values yourself. Hopefully I'm just missing something obvious and Otto can
yell at me for writing such a long email for nothing :)
Wishing I'd kicked the tires more when this first came out,
--
Jeremy Clarke | http://jeremyclarke.org
Code and Design | http://globalvoicesonline.org
More information about the wp-hackers
mailing list