 email
)';
Notes
A. Do not add ID column. The ID column is automatically created and set as the primary key in the table. It's used to store the object ID for future reference. Object ID can be the post ID, user ID, or term ID depending on what meta type the table is used for.
B. The column names must match custom field IDs, one column per custom field. If you create a column to store a group, then the column name must be the top-level group ID. Don't create columns for sub-fields.
C. The table name doesn't need to include the WordPress table prefix. The extension does not put any constraints on you to define the table name. If you want to include the WordPress table prefix, do this:
global $wpdb;
MB_Custom_Table_API::create( "{$wpdb->prefix}my_custom_table", [
'address' => 'TEXT NOT NULL',
'phone' => 'TEXT NOT NULL',
'email' => 'VARCHAR(20) NOT NULL',
] );
D. The extension uses WordPress recommended method to create a custom table, which means if the table already exists, the code will do nothing. Although, it's recommended to run the code that creates custom tables only when activating your plugin, like this:
register_activation_hook( __FILE__, function() {
MB_Custom_Table_API::create('my_custom_table', [
'address' => 'TEXT NOT NULL',
'phone' => 'TEXT NOT NULL',
'email' => 'VARCHAR(20) NOT NULL',
], [ 'email' ] );
} )
But if you can't run the code when activate your plugin, it's totally fine to run the code with the
init or
plugins_loaded hook.
Using existing tables
You can also use an existing table to store your data. The table can be manually created by a plugin, a theme or any tool like phpMyAdmin. To use it with Meta Box:
- The custom table must have the ID column. It's required to connect entries in the custom table with WordPress posts, terms, or users table.
- The columns in the custom table much match the field IDs in your meta box.
Connecting custom fields to a custom table
To tell a field group to use a custom table to store custom fields, you need to specify 2 parameters
storage_type and
table like this:
add_filter( 'rwmb_meta_boxes', function( $meta_boxes ) {
$meta_boxes[] = [
'title' => 'Meta Box Title',
'storage_type' => 'custom_table',
'table' =>'my_custom_table', // Your custom table name
'fields' => [
[
'id' => 'address',
'name' => 'Address',
],
[
'id' => 'phone',
'name' => 'Phone',
],
[
'id' => 'email',
'type' => 'email',
'name' => 'Email',
],
],
];
return $meta_boxes;
} );
Column names and field IDs
Again, column names have to match your custom fields' IDs, one column per custom field. If you create a column to store a group, then the column names must be the top-level group ID. No need to create columns for sub-fields.
Now you can go to the edit post screen (or the edit user profile if you use the meta box for users) and save the post. You'll see the data is saved in the new custom table instead of the post meta table.
Video tutorial
Getting field value
Use the helper rwmb_meta() function to get a field value. The only difference is you need to specify the table name in the 2nd argument:
$args = [
'storage_type' => 'custom_table',
'table' => $table_name,
];
$value = rwmb_meta( $field_id, $args, $post_id );
echo $value;
Also, note that the call to the custom table will be cached, e.g. if you call the helper function several times for the same
$post_id, it will only query once. This technique will improve the database performance.
You can also use the
[rwmb_meta] shortcode to display a field value. You need to set the shortcode attributes similar to the
rwmb_meta() helper function:
[rwmb_meta id="field_id" storage_type="custom_table" table="table_name"]
Group fields
For group fields, it's worth mentioning that the whole group value, including sub-fields values, is saved as a serialized array in one column. So, they're not flat as other fields.
That means:
- When you create a table, please create only one column for the group (even if that group contains many sub-fields or sub-groups). And the column name must be the group ID.
- The group value is serialized, you cannot make SQL queries against the sub-fields values. Thus, you don't benefit from the custom table structure. So, be careful to decide on what fields should be in groups and what fields should not. It's recommended to use groups only for data storing, not for querying.
While the data of the group is serialized, it will be unserialized when getting via helper functions. So you don't have to unserialize yourself.
Query posts with WP_Query
It's important to understand that the plugin doesn't hook to the
WP_Query to get posts by custom fields stored in the custom table. In other words, using
meta_* in
WP_Query for custom fields won't work.
To get posts by custom fields in the custom table, you need to make an extra query to get the post IDs first. Then use these IDs to get full post objects.
Here is an example:
global $wpdb;
$ids = $wpdb->get_col( "SELECT ID FROM your_table WHERE field1 = 'value1' OR field2 = 'value2'" );
if ( empty( $ids ) ) {
echo 'There is no posts';
} else {
$query = new WP_Query( [
'post_type' => 'post',
'post__in' => $ids,
] );
// Do something
}
This technique also works with terms and users.
Custom models
Besides custom tables for built-in WordPress posts, terms and users, the plugin allows you to create custom models, which mimic the WordPress posts, but store the data completely in custom tables. So you don't need to connect to posts, terms, or users anymore. And the data is stored only in one table, which is more efficient.
Pros:
- Better data structure, because you can define the custom table to match your needs.
- Don't mess with WordPress tables. You manage data on your own.
- Complete CRUD for models so you can create/edit/delete them quickly.
- Compatible with all Meta Box field types.
- Use the similar Meta Box and WordPress API/UI to show a list of models or edit models.
- Compatible with MB Admin Columns extension to show fields in admin columns.
Cons:
- Models don't have front-end templates like posts. You won't have permalinks for each model and their archive. Models should be used for managing data. If you want to have the power of the templates, then you should use the normal custom tables above.
- Limited compatibility with some extensions such as MB Relationships and MB Views.
Usage
To create and use custom models, you need to follow 3 steps below:
Step 1: Register a model
Registering a model is very similar to a custom post type in WordPress, with fewer parameters. The code below registers a custom model
transaction.
// Step 1: Register a model.
add_action( 'init', function() {
mb_register_model( 'transaction', [
'table' => 'transactions',
'labels' => [
'name' => 'Transactions',
'singular_name' => 'Transaction',
],
'menu_icon' => 'dashicons-money-alt',
] );
} );
List of labels:
Step 2: Create a custom table for the model
Creating a custom table is similar to the section above, except for one thing: you must specify the 4th parameter as
true to indicate this is a table for models.
// Step 2: Create a custom table for the model.
add_action( 'init', function() {
MetaBox\CustomTable\API::create(
'transactions', // Table name.
[ // Table columns (without ID).
'created_at' => 'DATETIME',
'amount' => 'BIGINT',
'email' => 'VARCHAR(20)',
'gateway' => 'TEXT',
'status' => 'VARCHAR(20)',
'screenshot' => 'TEXT',
],
['email','status'], // List of index keys.
true // Must be true for models.
);
} );
Do NOT create an ID column. It's automatically created (primary key, auto-increment).
Step 3: Register fields for the model, corresponding to the custom table structure
Registering fields for models is the same as for