Years ago, I wrote a post in which I shared a public function to determine if the user had permissions to save information to the WordPress database. You can see the original gist in all of its aged glory (along with the solid comments) here (it’s five years old, even – wow).

Secure WordPress Form Submission: The OG

As with anything programming related, time passes, things are refined, and things [hopefully] get better than they were before.

Though I still use and recommend a variant of the user_can_save (or userCanSave) function, I also think it’s important to go through the process of separating out the process of verifying the request.

So now it’s not just about determining if the user has permissions, but it’s about verifying the security information coming from the client – be it via a post back to the server or a request made via Ajax – and doing so using good programming techniques that align both with WordPress and with PHP.

To be clear, this is more about secure WordPress form submission from an options page or a settings page than it is, say, a form coming from a template. That’s another post for another time.

But still, there are plenty of us working on building applications on WordPress and that require the following.

Secure WordPress Form Submission

In this post, I’m not going to concern myself with going through the details of determining if something is an autosave or a post revision.

Secure WordPress Form Submission: Autosaving

However, I am going to walk through the process of taking a function that’s responsible for validating incoming information and doing so using a modern approach using object-oriented practices and both WordPress APIs and PHP functions.

1. Starting at a Generic Level

From the foundational level, let’s assume that there’s a base class from which there are other subclasses that leverage this function. This tells us we need to use the protected visibility modifier.

We also know that we’re going to be dealing with a WordPress nonce value and a related action. This means the function’s signature will look something like this:

2. Sanitize the Data, Verify the Nonce

As per anything that’s posted to the server, we know that we’re going to need to verify the data is set and if so, we’re going to need to sanitize the information.

This means we’re going to need the following functions:

And we also know that we’re going to need to verify the nonce, so we’re also going to need wp_verify_nonce.

3. A Working First Pass

A working first pass of this function may look something like this:

But what if someone is sharing data that’s sent a POST request (versus a GET) request? Then we could modify the function to look something like this:

And this would be sufficient. But if we really want a given function to be as pure as possible, then we could break this up even further.

4. A Function For Each Purpose

Given the code above, we know that we need to handle both GET requests and POST requests. PHP offers a filter_input function that’s helpful, easier to read (well, this is subjective), but also passes several code quality inspections.

Furthermore, we can use a simple factory-esque function to separate the logic into to separate functions like this:

Secure WordPress Form Submission: Factory

First, we need to write two separate functions – one for a POST request:

And one for a GET request:

Then we can tie it together in the original function like this:

Cleanly Managing Incoming Requests

Perhaps this looks like a complicated way to handle a simple solution given the initial set of code that was shared.

That’s certainly possible especially if you’re under the constraints of time or don’t care as much about breaking things into the smallest possible atomic (or even testable) components.

But if you’re looking to write object-oriented code with the highest degree of precision, maybe this process will help with exactly that.

Granted, this is just my process. I’m not saying it’s the way, but it’s a way. And if you have an alternative, I’m always welcome to read more and discuss it on Twitter. 🙂