As the name suggests, the Metabox
class helps you build a custom WordPress metabox. A metabox is a UI container, attached to one or more post types, where you can define and display any custom content.
By default, when you create a metabox with the framework, it is setup to display custom fields. But you are free to add any content into a metabox. See below for customizing the metabox.
In order to create a metabox for your post, page or custom post type, you have to use the make
method and pass it a unique identifier and a screen parameter. Then, you register the metabox by calling to the set()
method like so:
use Themosis\Support\Facades\Metabox;
Metabox::make('properties', 'post')->set();
The above example will display a metabox with a title of "Properties" in a WordPress post edit screen. It will also display an empty layout as it is configured to display custom fields by default.
You can also attach a metabox to multiple post types by passing an array as a second parameter:
use Themosis\Support\Facades\Metabox;
Metabox::make('properties', ['post', 'page'])->set();
When registering a metabox, you first need to pass a unique identifier. By default, the class is using that id as the metabox title. In order to provide a custom title for your metabox, you may use the setTitle()
method like so:
Metabox::make('properties', 'post')
->setTitle(_x('Product details', 'metabox', 'textdomain'))
->set();
By default, a metabox context is set to normal
. If you want to change the metabox context (display area), you can use the setContext()
method:
Metabox::make('properties', 'post')
->setContext('side')
->set();
By default, a metabox priority is set to default
. If you want to change the metabox priority, you may call the setPriority()
method:
Metabox::make('properties', 'post')
->setPriority('high')
->set();
By default, the metabox is configured to handle custom fields. If you want to create metabox with a custom user interface, read the section customize the metabox below.
Since release 2.0, the framework is bundled with new custom fields managed by a RestAPI and ReactJS components. The metabox class leverages the Field class in order to add custom fields.
Please note that not all form fields are available on a metabox. Please see the field guide for more details.
In order to add custom fields to a metabox, use the add
method:
use Themosis\Support\Facades\Field;
Metabox::make('properties', 'post')
->add(Field::text('author'))
->add(Field::text('isbn'))
->add(Field::integer('publication_year'))
->set();
The above example will display a metabox with two text fields and a number field. The new Field API for metabox is now handled through JavaScript only and built with ReactJS components.
In order for a user to save the data handled by the custom fields, each metabox displays a "Save" button below. If the user click on the main "Publish" or "Update" button for the post, the metabox custom fields data will not be saved. Custom fields data is now saved through a custom RestAPI.
Note: the metabox and field RestAPI is using the default
api
middleware group. Be sure to not change the group name.
It is also possible to organize custom fields by group using the add
method and by passing a section instance with custom fields:
use Themosis\Support\Facades\Field;
use Themosis\Support\Facades\Metabox;
use Themosis\Support\Section;
Metabox::make('properties', 'post')
->add(new Section('general', 'General', [
Field::text('author'),
Field::text('publisher')
]))
->add(new Section('details', 'Details', [
Field::text('isbn'),
Field::media('cover')
]))
->set();
The above example will display fields organized within 2 tabs: "General" and "Details". Each time you define a section, you have to provide a unique identifier as the first parameter and a display label as the second parameter. The section fields are then defined into the third parameter as an array.
You need to define at least 2 sections of fields in order to trigger the tabs layout.
In order to customize your individual fields, please read the documentation on the field guide for more information.
The new field API is automatically prefixing custom fields names. By default if you add a text field with a name of author
, it stores the value with a meta key of th_author
in the post meta table.
If you want to change the default prefix for your metabox fields, you may use the setPrefix
method:
Metabox::make('properties', 'post')
->setPrefix('wp_')
->add(Field::text('author'))
->set();
Make sure to call the method before adding your custom fields.
Prefixing is enabled by default to avoid any conflicts with core reserved terms and data coming from third party plugins. If you do not want to use prefix, simply pass an empty string to the
setPrefix
method.
The new field API is leveraging the illuminate/validation package from Laravel in order to validate custom fields data. The new user interface also provides error display on each field and also on tabs if you're using groups.
In order to validate data, you need to define a set of rules
on a per field basis. Here is an example of a text field:
Metabox::make('settings', 'Parameters')
->add(Field::text('author', [
'rules' => 'required|min:3'
]))
->set();
The above example sets the author text field as a required value and must have a length of at least 3 characters. If the validation fails, the field data is not saved and the metabox is displaying an error message below the field.
For a list of available validation rules, please read the official documentation.
When a validation fails, the metabox is displaying a "Saved with errors" message in its footer. This means that valid field data is saved in the database while failed one is not.
By default, validation messages for the overall application are defined into a validation.php
file stored in a directory with a name equivalent to the current loaded locale within the resources/languages/
directory at project root.
If you want to customize the errors messages for your metabox fields, you can pass a messages
property to each field with an array containing key value pairs. The key is the validation rule and the value is the message.
Let's customize the fields from previous example:
Metabox::make('settings', 'Parameters')
->add(Field::text('author', [
'rules' => 'required|min:3',
'messages' => [
'required' => 'Required, the :attribute field is.',
'min' => [
'string' => 'At least :min characters, the :attribute must be.'
]
]
]))
->set();
The :attribute
and :min
are validation placeholders terms. In order to know what type of messages you can define per rule, follow default messages defined into the validation.php
file.
On validation, the :attribute
placeholder term is replaced by the field name (without the prefix). If you want to provide an attribute name different than the field name, you may pass a placeholder
property to the field like so:
Metabox::make('settings', 'Parameters')
->add(Field::text('author', [
'rules' => 'required',
'placeholder' => 'guy'
]))
->set();
The above example will display the following error message:
The guy field is required.
When using the metabox with custom fields, the user interface is displaying texts regarding its current state. Each label can be translated. A translation is associated to a key name. Here is the list of default labels applied to a metabox:
[
'done' => __('Saved'),
'error' => __('Saved with errors'),
'saving' => __('Saving'),
'submit' => sprintf('%s %s', __('Save'), $metabox->getTitle())
]
You can override the default labels applied to a metabox by calling the addTranslation
method and pass it the key name and the translation as a value:
Metabox::make('properties', 'post')
->add(Field::text('author'))
->addTranslation('done', 'Success!')
->set();
You can add as many translations strings as you want to your metabox. Especially when building a custom user interface with it.
A metabox instance provides methods to retrieve translations and use them in your interface. You can use the getTranslations
method to get the full list of translations or you can call the getTranslation
method to grab a specific one:
$box = Metabox::make('custom', 'Options')
->addTranslation('title', __('A title'))
->addTranslation('subtitle', __('The subtitle'))
->set();
$all = $box->getTranslations();
$title = $box->getTranslation('title');
You will rarely need to grab a metabox translation out of it. Those methods are useful when you create a custom metabox user interface and want to get optional translation in your interface/view.
In order to retrieve the custom fields data, you can use the core get_post_meta
function. Here is an example based on an author
custom text field:
$author = get_post_meta($post_id, 'th_author', true);
Please note that custom fields meta key names are now using a prefix by default.
If you want to create a custom user interface, you can do so by passing a callback to your metabox using the setCallback
method:
Metabox::make('custom', 'post')
->setCallback(function () {
return view('metabox.custom');
})
->set();
In the above example, the metabox is displaying the metabox.custom
view. From a metabox callback you can return a Renderable
instance (view), a string or even a Response
instance.
The metabox API can also handle a class callback using the ClassName@method
syntax:
Metabox::make('custom', 'post')
->setCallback('App\Metabox\Custom@show')
->set();
Just like in action or filter, you have to provide the full class name, with its namespace, for the callback.
By default, the metabox callback receives as a parameter an $args
array containing an instance of your metabox, an instance of the current post and the screen it is attached to:
Metabox::make('custom', 'post')
->setCallback(function ($args) {
return view('metabox.custom', [
'post' => $args['post'],
'metabox' => $args['metabox'],
'screen' => $args['screen']
]);
})
->set();
You can also provide additional data to your metabox by using the setArguments
method and pass it an array of key value pairs:
Metabox::make('custom', 'post')
->setCallback('App\Metabox\Custom@show')
->setArguments([
'users' => App\User::all()
])
->set();
Those arguments are then provided to your callback:
<?php
namespace App\Metabox;
class Custom
{
public function show($args)
{
return view('metabox.custom', [
'users' => $args['users']
]);
}
}
You can configure your metabox to display based on current user capability. In order to do so, you may use the setCapability
method:
Metabox::make('custom', ['post', 'page'])
->setCapability('edit_posts')
->set();
You can limit metabox display to WordPress templates by calling the setTemplate
method:
Metabox::make('custom', ['post', 'page'])
->setTemplate(['featured', 'holidays'], 'post')
->setTemplate('team')
->set();
The setTemplate
method accepts as a first argument a template name or an array of templates and as a second argument the screen|post type to which the templates are associated to. By default, the screen parameter is set to page
screen.
You can chain the
setTemplate
method as many times as you want.
Made in Belgium