Support » Developing with WordPress » Using settings API, field is emptied when there is validation error

  • Resolved Guyinpv

    (@guyinpv)


    I’m using the settings API to create a custom settings page for my plugin.
    The setup is by the books. Use add_options_page() and then add_settings_section() and register_setting() and add_settings_field().

    Everything is a success, my setting is saved to the DB and recalled when the settings page is opened.

    I am using sanitize_callback on the setting. The field is an email field and so I’m checking the field using PHP’s filter_var() function.
    If the email is invalid, I use add_settings_error() and send the error, this works fine and I see the error on the settings page. If there is no error, I return the email and it saves to the DB.

    The problem is that when there is an error, it returns to the settings page and the field has been blanked, emptied, and the previous value in the database was also blanked.
    Let’s say they had a valid email in the DB like “me@me.com”. Then they go to change the email “bademail@” and try to save, it will fail the sanitize and send the error message back, but now the email field will be empty and the previous email in the DB is also emptied.

    I’m not sure if this is normal behavior. I would think that if sanitize fails, it would not save any value, and the previous value would still be in the DB. Secondly, the user should still see what they previously typed in the field so they have a chance to fix the error and submit again. If the field is emptied, they have to type it all over again, which could be bad.

    How do I accomplish these two things then?
    1) If the sanitize fails and I use add_settings_error(), how do I let the user still see what they had typed so they can try to fix it?
    2) If the sanitize fails, how do I stop it from saving empty data to the DB and overwriting the previous good value?

Viewing 3 replies - 1 through 3 (of 3 total)
  • Moderator bcworkz

    (@bcworkz)

    Sounds like you’re using the sanitation callback as a validation function. I’m assuming your callback is not returning an invalid email. Sanitation is for cleaning up a value, not rejecting it. A sanitation callback should return whatever it is that should be saved, whether it’s the original value or a modified new value. By not returning anything, the field is blanked out.

    AFAIK, if you want to do proper validation, it must be done elsewhere prior to sanitation. I’m not sure the API as a hook for validation or not. You could always do validation client side with JavaScript. The value submitted still must be rechecked server side since JavaScript can be overridden. But if someone were to attempt to bypass JavaScript validation, they cannot be surprised by unusual behavior like their field being blanked out.

    Thread Starter Guyinpv

    (@guyinpv)

    You are correct, there is no other validation method other than the sanitize callback. This appears to be the normal place where people should use the add_settings_error() function to send their errors, unless I missed some “normal” or “proper” way to do validations a different way?

    I did get around my issue by saving their “bad” value into a transient so I could output it again on my page, this allows them to see their previous bad value and adjust it.

    The thing that irks me is that the sanitize function requires me to return the value, which then requires it to be saved to the DB, expending a useless DB query to save a value that hasn’t changed.
    Maybe that’s a technical hurdle, I don’t know, but if a value doesn’t change, maybe there should be a way to just “ignore” so WP doesn’t have to do a needless query?

    So then, I solved my problem by returning the current DB value (in the event of an error), or I return the new sanitized value, using sanitize_email() function. Or I return blank, because I allow the user to empty the setting if they want no value.

    And then I use the transient trick to hold their “bad” entry and show it back to them. I immediately destroy the transient so that if they refresh the page or something, it won’t show up again.
    I realize that the transient won’t work if they don’t have WP_CACHE set to true, but that’s ok, the field just ends up blank or showing the previous value in that case.

    Thanks!

    Moderator bcworkz

    (@bcworkz)

    Transients are an interesting work-around, nicely done! TBH, I never cared that much for the Settings API. Sure, it can be handy and it presents a consistent UI, but it seems too cumbersome for what you get from it. And it doesn’t allow for much deviation from its intended rather simplistic purpose. Realizing it doesn’t have a validation mechanism makes me like it even less.

    I tend to develop my own settings page outside of the API. I’ve not found it to be that much more difficult, but it gives me way more flexibility.

Viewing 3 replies - 1 through 3 (of 3 total)
  • You must be logged in to reply to this topic.