This post is part of a series on Sanitization with the WordPress Settings API. Here is Part 1.

Yesterday, I started talking about how to sanitize multiple values with the WordPress Settings API.

The idea behind the post was to kick off a short series of additional posts that expand on some of the object-oriented articles I wrote a few weeks ago. Secondly, the purpose is to show how we can go about taking input from a Settings API-based page and then use conditionals to validate each of the incoming values as well as add errors messages for those that are required.

In this post, I’m going to walk through the process of actually validating information that’s coming from the page that uses the Settings API. In the follow-up post, I’ll talk about how to go more in-depth with validation, required fields, and how to add error messages to your pages.

But for now, we’re just worried about multiple values.

The WordPress Settings API and Array Sanitization

At this point, I’ve mentioned multiple times about the </em>sanitize<em> method that comes with working with the Settings API and I’ve shown a number of examples but they’ve all been relatively simple. And that’s fine when you’re trying to demonstrate the purpose of how the API works.

But when your pages are a little more complex, then the odds that you’re going to be working with just a single value is really small. As such, we need to know how to handle multiple values when they come into the sanitize method.

On top of that, we need to know how to validate them appropriately – that is, are they textareas or radio buttons or whatever. And that’s where saving multiple types of values comes into play.

So for the purposes of example, let’s say that we have a page that has a few input elements all of which are of type text and we have a select element that will contain the list of provinces, countries, or states depending on where you live.

Eventually, we’ll determine which one of these is required but, for now, we’ll look at how to sanitize all of the information.

First, let’s assume the page looks something like this:

An Example Settings Page

An Example Settings Page

For now, don’t worry about anything such as the phone number, email address, or URL. We’re just concerned with the first set of fields.

Know Your Names

First, the key thing to note about this page is that each element has a unique name attribute. This is how information is saved and retrieved from the database. For example, it would not at all be uncommon to have the following name attributes for each of the above fields:

  • address_1
  • address_2
  • city
  • province
  • postal_code

It’s important to take note of those names because when it comes time to sanitize all of that information, you’re going to need to know the names.

Sanitizing Multiple Values

And this is where programmers can get hung up longer than necessary: Should we be using if/else statements or should we be using switch/case statements? Personally, I like the latter but it’s because I find it more readable.

This is purely a personal preference and the point of the post has nothing to do with which is write or wrong. If you like to use if/else statements more than the alternative. Go for it – they’re easy enough to translate, anyway.

Okay, so with that said, let’s setup our sanitize method so that it now looks at each of the values of the $input collection that’s passed into it and, y’know, sanitizes it before returning it and saving it to the database.

Not too difficult to follow, right? Notice that we’re also able to sanitize the select element’s value the same as our input element. Nice.

Anyway, since we know that each element on the page as a name attribute that corresponds with its field, then we can sanitize the input field, write it to the new array, and then return that array to WordPress to save.

But here’s the thing: The code above is redundant. It also doesn’t account for cases when the values aren’t set at all. So why bother showing something like this?

When it comes to learning how to write code in a way that’s testable, that reads well, that’s less redundant, and that’s more secure, I find that it’s often more effective to look at what you might see, understand the pitfalls, and then see how to improve it.

And that’s what we’re going to do.

Approving All Of The Above

As mentioned, the code above is redundant. In some cases, it won’t always be that way, but the gist of what we’re doing is the same for each element of the $input collection: We’re simply sanitizing a text field.

To that end, we could simply just setup a loop, iterate through the collection, update the new collection, and return it. Take a look:

But wait – what if a value gets through the serialization process where the value isn’t set? We need to add one more check to set a default value. In this case, I’m using an empty string, but you may find yourself using something like a -1 or null or something else. It all depends on what you’re going to be doing with the data once you retrieve it.

In short, we’re adding a check to see if the value is set and, if it’s not, then we’ll provide an empty value; otherwise, we stick with what the user provided (and sanitize it accordingly).

A Note About Developer’s Code

Now, is this the definitive way to do this? No. Other developers have their strategies and they are likely different though just as effective – probably more so in many cases – as what you’ve seen above. On the other hand, some other code is not worth studying because it could lead you down the wrong path.

I believe that, at some point, we generally have intuition as to what things are generally better than others, but if not, it never hurts to ask. I mean, you’ve nothing to lose, right?

When you’re reading posts on code like this, remember that a lot of the code that you see is based on the developer’s level of experience, the types of projects they work on, and how they tend to tackle problems.

That said, this is one method that I’ve found to be very effective. If other people chime in with their own comments linking to other code, be sure to review it – you (and I!) may learn something even better.

Moving Forward

Honestly, when you’re dealing with something as straightforward as similar elements, that’s a great strategy. But the point of showing the switch/case first, is to get you thinking about how to handle more complex cases when you’re dealing with additional types of settings.

First, get something working, then refactor until it’s a bit more elegant, rinse, repeat, and release. Eventually, these types of things become second nature but it takes some time – and by time, I mean it can take years. To be clear, I still work on trying to improve the code I write almost daily.

Anyway, on the contrary, the switch/case sets us up for how we can handle fields on an individual basis such that we can handle required fields and error messages in a more suitable fashion.

But we’ll take a look at that in an upcoming post.

Series Posts

  1. Sanitizing Multiple Values with the WordPress Settings API
  2. Sanitizing Arrays: The WordPress Settings API
  3. On Pause: The WordPress Settings API
  4. Refactoring Input Sanitization with The WordPress Settings API
  5. Validating Input via the WordPress Settings API
  6. Validation and Sanitization in the WordPress Settings API
Category:
Articles
Tags:
,

Join the conversation! 7 Comments

  1. Hey Tom,

    In your last code example, you’re doing the following.

    // Loop through the input and sanitize each of the values

    foreach ( $input as $key => $val ) {

    $new_input[ $key ] = ( isset( $input[ $key ] ) ) ?
    sanitize_text_field( $val ) :
    '';

    }

    To be honest, I’m not super sure what you’re trying to do here but in any case, the isset check is redundant. You’re iterating over the keys of the $input array, so the current index is always set.

    Rock on!

  2. How about some love for array_map? If you can use a PHP closure, you can do it real concisely, like:

    function sanitize( $input ) {
    return array_map( function( $val ) {
    return sanitize_text_field( $val )
    }, $input );
    }

    If you’re still supporting 5.2, you’d have to name the function, but you can do the basic thing.

    Also, from the look of it, sanitize_text_field() will actually coerce falsy values (null, false, etc) to an empty string by default, so you don’t really need to do that. Doing it here does certainly has teaching merit though, because as you mention someone may want a different default. (Source for the function itself at https://core.trac.wordpress.org/browser/tags/4.2.2/src/wp-includes/formatting.php#L3866, coercion happens in first line of wp_check_invalid_utf8.)

  3. Someplace or another I have a library I coded up perhaps 6 years ago? Was for Jooml’r that essentially was towards political sites where alot of interactions were at hand. It was sorta a “Data Washing Machine” singleton that was also paired with an exceptions singleton (tasked with only dealing with the Washing Machine) and a Logger. Not sure where that code is, here someplace on a PC long since pulled from service. But worked really really well with minimal overhead and consistent visual outputs.

    Rules and which forms of data cleansing/validator were to be used all sat in specific XML files it’d consume. So numeric be one XML files, common string another, formatted inputs another, collections another. All tagged via the input name. One XML per form describing the varied inputs criteria’s, ordering etc.

    We were planning making a dynamic form builder around it but the need did not arise.

    It’s all OOP and was sorta inspired by some VB ASP.NET code had run across someplace.

    Might have been on code project or one of those places, Essentially raised exception events which as I recall I simulated via a simple dispatcher similar in concept to “hooks” but doing data transport as well.

    I’d also done a registry singleton that we’d planned pair up with it but never did merge the codebase. Idea was to take in an array .vs. the XML for a given form or multi-part form as well as provide a more flexible & granular capability towards page assets / page display elements / layouts removing quite a bit of DB to and fro.

    This is seldom (surprisingly) thought of in PHP code. PHP as we know has ALOT of take in arrays as they map nicely to C++ whether that native arrays or even pointer based allocated/de-allocated ram.

    Also why OOP doesnt map real well and thus has a significant overhead in PHP or at least in compare to lingo’s which were native OOP from word go and of course CPU advances in ways that ram addressing can be structured in favor of complex objects/collections.

    Its a very fast way to bring in fixed assets or assets that seldom change. Basically DB caching (sorta kinda) to arrays which is usually how many a PHP app brings input from a DB.

    Several years back I was asked by a operation to try speed up PHP ProBid for them and I did quite a bit of modification on it in what basically is static data until said data is changed. Call it “stupid cache” lol.

    For example, take categories. Its structured data that stays static until a site admin might add or remove or edit them. Yet, every single page clunking out to the DB to fetch that information. Breadcrumbs / sub tree’s clunking out to the DB every single page. So I just wrote a little bitty piece of code so anything categorical edit took place, write the new array out. Since its an administrative function its not done frequently. Not caching in a traditional sense but much more an old form of sense. Instant 12%+ performance every page load. I then went and hammered the code itself that drive the front end displays, average 15%-18% increase in performance every page.

    Yes, ate a bit more ram taking in a sizeable array from file (I probably could have optimized it further) but I viewed it as the page session throughput was considerably faster and thus release of said assets is faster. But the amount of Ram overhead was really pretty scant as the DB Query was essentially doing the same thing bringing in an array and then post processing it. I did the processing so the forest was better ordered and simply need be read in.

    In the old days of Video Games we’d do all sorts of similar funk during the blanking periods of a raster scan display. Old Electron Gun based CRT’s, TV’s. They start up left top of the picture tube. Draw one scan line, electron gun shut off, return to the left side, drop down one scan line, draw that one.

    That “off time” is a horizontal blanking period. CPU can be doing work during it. When the electron gun reach the bottom right of the CRT, shut off, return all the way to the left top and start the process all over again. Thats a vertical blanking period. LOTS of time for the CPU to do work. Raster scan do that “nn” times per second, TV 60HZ (cycles), so 60 times per second. Seems fast. Slower than snail snot in compare to CPU operating at Millions of cycles per second Mhz in the day, Now GHZ of course, billions of clock cycles per second.

    During those blanking periods do all sorts of things, build sprite’s, collision detection on and on.

    Collisions detection in games was the forefront of GUI’s and the mousie. Rectangles intersecting other rectangles. Was all done in assembler, lists of objects with ID’s, linked lists of bounding rectangles and just plow through them, “Look my bullet rect intersects the little space invader guy’s rectangle” cream him, remove the beastie, set its bounding rect to hit (not removing the rect) remove the bullet sprite rect, add points, on and on. Arkanoid, breakout, lots and lots of variants. But all pretty much under the hood pretty similar. The advent of video cards becoming computers unto themselves was amazing (and sorta depressing). Its really what creamed alot of other innovative computers and differing ideas on how to deal with the varied forms of hardware/software assets and capabilities.

    Just as that industry went its way, we’ve saw much the same on the Net. Perhaps just natural evolution. As PC’s for example became “boxed in” components even to the point Apple went, “welp, cant beat em join em” in hardware zones we are at the beginning stages of really “Short web” seeing the same.

  4. Just to compress a lite bit more the code, the initizalization of:

    $new_input = array();

    can be done like:

    $new_input = [];

    Just for the sake of less typing :D.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.