From PHP to WordPress
If you are experienced in programming and in PHP, you know that saving data coming from a form basically involves these steps:
- validation
- sanitization
- connection to database
- store value in database
even if "plain" PHP would work for all of them, WordPress has helpers and specific best practices for them.
Validation
This is the only part WordPress won't help you much. PHP is your friend here.
Sanitization
WordPress has different helpers for sanitization.
For data coming from forms, there are different sanitize_* functions, like sanitize_text_field()
that you can use. Find them here. Note that not all the functions you'll find in the link are useful for the scope.
Connection to database
In WordPress context, you don't connect to databse. You let WordPress do it, then you use the database API to execute queries on database.
The WordPress database API is summarized in the wpdb
object, available in the global $wpdb
variable.
There's nothing else to do. WordPress will also take care of close the connection when necessary.
Store value in database
A documentantion on global $wpdb
API is available here. As you can see there, there are a lot of methods.
Probably the most useful are the helpers for CRUD oerations:
get_results()
/ get_row()
/ get_col()
/ get_var()
insert()
update()
delete()
It is impoertant to note that data sanitized with sanitize_*
functions introduced above, should be escaped with database-specific methods before being saved into database.
For the scope there's the method prepare()
that provides a way to escape SQL statements using a sprintf
-like syntax.
Form pages and form processing routines
Everything said above is necessary to process the data coming from forms.
However you also need:
- a "page" where to place the form
- a "place" where to place form processing routine.
Frontend and backend form pages
In WordPress we can distinguish of two categories of forms: forms who belong in frontent and thosee in who belong in backend.
For frontent forms, you will probably place all the HTML in one of the templates, and that's it.
For backend forms, there are many possibilities.
If you want to store values that releates to a post, you will probably want to add a metabox and place a form there. Actually, in this case you don't use a "full" form, but just form inputs that become part of the whole post edit form.
The same approach can be taken, using specific "hooks", to add fields to edit / creation forms for taxonomies, users and so on. This website and the web in general are full of examples and guidance about this.
In case the data you want to store are completely unrelated to any WordPress core "entity" (for example you are going to build an option page for a custom plugin) you probably want to register an admin page and place the form there.
Form processing
How to process data coming from a form depends on how you printed it.
If you used any of the way to add fields to existing WordPress forms, you can't just use your own routine, but you have to hook the existing routine and process your data.
For example, if you added a post metabox, your fields were added to post edit/creation form, and will need to hook save_post
or any other hook fired when WordPress save a post, to check for data coming from your form fields and process them.
If your form comes from frontend, or you created a completely new form in backend, you could be tempted to create a file that process the form.
This won't really work, because you are going to use WordPress environment (remember the $wpdb
object?) and so you would need to bootstrap WordPress manually, which is not rellay recommended.
Instead you could:
- send the form to the same page that contains the form and place processing code on top of markup. This is really not suggested because mixing processing code and markup code is a mess to maintain.
- send the form to
admin-ajax.php
(the full URL is obtained via admin_url('admin-ajax.php')
) and then use "admin_ajax_{$action}"
/ admin_ajax_nopriv_{$action}
to hook your routine. See Codex about AJAX_in_Plugins
- send the form to
admin-post.php
(the full URL is obtained via admin_url('admin-post.php')
) and then use "admin_post_{$action}"
/ admin_post_nopriv_{$action}
to hook your routine
- Use the REST API to register a custom route and then process the form in the REST route handler
On data structure
WordPress has its own tables and a specific data structure.
Using dbDelta
function you could create custom tables and the $wpdb
object is still able to operate on those, however this should be avoided as possible.
Reason is that custom tables in WordPress are cumbersome to maintain (WP is missing things like migrations or fixtures) and also using custom tables you miss the possibility to use many of WordPress API that is available if you fit your data into WordPress core "Entities".
For example, if your data is related to posts you could use taxonomies or post meta to store them.
If data is user-related data you could use user meta, or terms meta for data related to taxonomy terms.
In case of "generic" data you could use options or you could use theme modifications in case of theme-specific confugration.
If you do so, when you need to retrieve/store data, instead of using wpdb
methods you can use specific APIs.
Taxonomies, post meta, term meta, user meta, options, theme modifications... provide methods to interact with data at higher level, simplifing the access to data and providing other benefits like cache, filterability, compatibility with other parts of core (e.g. customizer and REST API), compatibility with plugins...