Creating forms in WordPress can be difficult. By using OOP and WordPress hooks, you can create forms that can be extended as needed and also perform various tasks. With popular plugins such as Gravity forms or Contact Form 7, you might not need to create forms on a regular basis, but in some custom solutions you might have to create your own forms.

The code in this article can be used in any projects.

How to be Build an Extendable Form

Before we start coding, I want to make sure that you understand what is an extendable form and how to build one.

Extendable form can be extended by using WordPress filter hook to add new fields. By using OOP we will have access to the form object throughout the whole page load. We can easily validate the form and also show errors if any.

Validation of the form will be made inside the WordPress action init where any error will be registered using the object WP_Error.

Extendable WordPress Abstract Form

We will create an abstract form class so that we can then easily create various form classes based on the abstract class. By extending the abstract form class, we will only need to define how the posted data will be used and the default fields.

The array of errors will be an object of WP_Error class so that we can easily add errors as we validate various posted data. The valid label $valid will be true only if there are no errors. The array of fields will contain various field definitions. This attribute will be also extended by WordPress filter. The attribute $id is the unique ID of the form we create.

In the constructor method,  we assign the provided id to our attribute $id, we create a WP_Error object and assign it to attribute $errors and we set the default fields by using the method set_default_fields(). After that we create a dynamic WordPress fiter that will consist of ‘ibenic_form_fields_’ + the id of the form. So, if our form id is register_form our dynamic filter would be ibenic_form_fields_register_form on which we could hook functions that would use the provided fields and add additional ones by extending the array of fields.

The last thing is hooking a method form_submitted to action init so that we can get access to our posted data and then even redirect the user if needed because the headers are still not sent in that action.

Let’s now define that method:

Since our button that will submit our form will have its attribute name set to our form id we check if the form id is posted. If it is posted then we know that this form is posted and we can move on. We are setting the attribute $posted with our posted data so that we can access that data even in another method.

After that we validate the form inside the method validate_form(). If there are no errors, we are calling the method form_is_valid() which will be define in other form classes because each form could have a different scenario. If there are errors, then we set the attribute valid to false.

In the method validate_form() we pass through all the registered fields and perform validation tasks. First validation is to check if the field has a repeated value. This is common in password fields where we need to repeat a password. If there is a field that has a repeated value, we check that repeated value.

We assigned a static suffix ‘_repeat’ to our fields’ name so that we can distinguish and also get both values. If both values are not equal we add an error where the code of our error is our fields’ id.

If there is a sanitisation function, we are calling that function and passing our posted data from that field. After that we are also checking if that field is required. If the field is required, then we are also checking the field if it is empty or it has data after the sanitisation. If the data is empty, we add an error in the same way like we did before by add our fields’ id as the error code.

At the end of that method we are settings the sanitized data to our attribute posted so that we can use that data if the form is valid.

We have also defined an empty method form_is_valid() because this is a method that has to be defined in other classes that will be extended from our abstract class.

The last part of our abstract class is the rendering of our form:

We are here creating the form and setting our submit button with the name attribute equal to our form id. In that way, our method form_submitted() can check the superglobal $_POST variable with the same form id. If that form is submitted, the form id will exist in the superglobal $_POST variable.

We are also getting again through all our registered fields and create them. In this example, we do not go too deep into rendering fields and due to that I am presenting only input elements. Elements such as select or radio will need to be implemented also if you plan to use such fields.

That is your task! Try to implement them as an exercise. To get an idea how to create that, you can view my other tutorial How to create WordPress Menu Pages with OOP where we have already done that.

Let’s move on. When rendering those fields, we are also checking if there are any errors with the fields’ id as error code. If there are any, they will then be rendered below that field.

I have also created a dynamic action so that anyone can easily extend the form without entering fields in the dynamic filter. You will see how to use that in an example below.

Here we have also created the method set_default_fields() which is empty since an abstract form class does not know which fields it should have.

So here it is. Our abstract form class is created and we can now move on and create specific forms. For this tutorial, I will show you an example of a registration form in WordPress.

WordPress Registration Form Example

For our example we will first create our registration class:

Here we have extended our abstract form class with our registration class. In the constructor method we are calling the constructor of our abstract form class and then we are defining an action hook which will be used to render the form. This action can be used in a shortcode or in a template to display the form.

In the method set_default_fields() we have defined our default fields with parameters that we use when rendering or validating the form. Here we can see that the password is the only field with the parameter repeat set to true.

In this method we are getting our required fields that are used to create and register users. Once we have got all those fields, we are creating a new user. The returned value can be a WP_Error or an user id. If it is a WP_Error it means that something went wrong and we are setting our form to be invalid and we add a new error.

If the returned value is actually an user id then we are getting the required credentials for signing in the user. We are also setting a redirection url and applying a WordPress filter to it so that it can be changed outside the class. After that we are sending the user registration email and then we are signing in the user. After we have signed in the user, we are redirecting our user to our redirection url.

Somewhere in your plugin or theme you can add this to instantiate our class:

Showing the WordPress Registration Form

Now that our registration form is instantiated we can use our dynamic action that we did in our constructor method to render the form. This is an example of that:

In this function we check if we are on a page with a slug register (this can be a regular page with title Register). If we are on this page, we will call our dynamic action to render the registration form.

Adding new fields

If you want to add new fields to the form you can use something like this:

Do be aware that you must also add a new function to our action ibenic_form_is_valid_register_form which is a dynamic action that we have defined after we call our method form_is_valid(). We are passing our form object to that action so that you can easily add errors if needed or defining if the form is valid or not.


In this tutorial we have learned how to create extendable WordPress forms with OOP and WordPress hooks. WordPress filters and actions allow us to extend any functionality we want and by using OOP we can easily create base classes and extend the functionality of our class by using other classes.

Have you ever used OOP to create forms in WordPress? How do you like these examples? If you have any questions about rendering the select elements or radio elements please do let me know in the comments below.

Become a Sponsor

Posted by Igor Benic

Web Developer who mainly uses WordPress for projects. Working on various project through Codeable & Toptal. Author of several ebooks at

Leave a reply

Your email address will not be published. Required fields are marked *

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