Wondering how the Meta Box stores custom fields in the database? Understanding this can help you get the custom fields easily and understand the returned value from
get_post_meta or helper functions.
How fields are saved in the database?
In general, each custom field is saved as one row in the database, where the field
id will be the
meta_key and the value will be the
meta_value in the meta table. This is the same way that WordPress saves data with
- If you use custom tables, the field value will be saved in the column with the name equal to the field
- If you create a field for a settings page, the whole data for the settings page will be saved as an array in an option in the format of
['field_id' => 'field_value'].
The sections below describe how field values are formatted.
For non-cloneable fields, the plugin stores field value in the database in a WordPress-compatible way as follows:
- If a field has a single value, it will be saved in a single row in the post meta table.
- If a field has multiple values (set by
'multiple' => truelike
image, etc.), each value will be saved in a single row in the post meta table.
This way you can use
update_post_meta to update meta values and
get_post_meta to retrieve them.
For cloneable fields, values are stored as a serialized array in a single row in the database, unless you set
'clone_as_multiple' => true.
Using serialized data has some benefits:
- Works for all field types, including nested groups.
- Works perfectly with the helper function or with WordPress's
get_post_metafunction (WordPress automatically unserializes string and returns an array).
- Reduces the database size (number of rows), especially when you have nested groups of many fields.
However, serialized data has a big disadvantage: you can't query posts by serialized values.
For example, if you have a cloneable field
start_date for the
event post type, and you want to query events in May 2019 like this:
$args = [
'post_type' => 'event',
'meta_query' => [
'key' => 'start_date', // This field is cloneable
'value' => ['2019-05-01', '2019-05-31']
'compare' => 'BETWEEN',
$query = new WP_Query( $args );
Then it doesn't work.
To solve this problem, you need to enable the Clone as multiple settings for the field.
With that, Meta Box will save cloneable values in multiple rows in the database, where each row contains one value. That means if
start_date has 2 values
['2019-05-01', '2019-04-30'], it will be saved in 2 rows in the database, one for
2019-05-01 and one for
2019-04-30. The data is not serialized anymore. And thus, your above query will work!