How to Output Codestar Framework Group Field Values

Quick Summary
- Define a group field in a CSF::createSection() call with a button_title and inner fields, so editors can add as many entries as they need.
- Load the metabox array with get_post_meta(), take the group by its id and loop through the entries, each an array keyed by sub-field id, escaping every value.
- Codestar Framework 1.x sites define the group in metabox.config.php instead, but the data is stored the same way, so the same template code works.
A group field in a Codestar Framework metabox lets editors add as many sets of sub-fields as they need with a button, for example one row per car model and year. The framework saves the group inside the metabox’s post meta array, as a list of entries, each an array keyed by sub-field id. To output it, load the metabox with get_post_meta(), take the group by its id and loop through the entries.
The code below is for Codestar Framework 2, the current version, where metaboxes need the premium version. A short section at the end covers sites that still run 1.x. Reading a single Codestar metabox field explains how the framework stores metabox data and where the project stands today: the latest release, 2.3.1, is from January 2024.
Step 1: define the group field
Register the metabox with CSF::createMetabox() and add the group to one of its sections with CSF::createSection(), in your theme’s functions.php or the plugin that loads the framework:
if ( class_exists( 'CSF' ) ) {
CSF::createMetabox( 'mbhouse_project_meta', array(
'title' => 'Project Details',
'post_type' => 'post',
) );
CSF::createSection( 'mbhouse_project_meta', array(
'title' => 'Availability',
'fields' => array(
array(
'id' => 'car_year_lists_x',
'type' => 'group',
'title' => 'Year Data',
'desc' => 'Add availability for cars',
'button_title' => 'Add New Year',
'fields' => array(
array(
'id' => 'mb_car_year_details_av',
'type' => 'text',
'title' => 'Car Model & Year',
),
),
),
),
) );
}mbhouse_project_metais the metabox id. All the metabox’s fields are saved together in one post meta entry under that key. Setpost_typeto the post type that needs the box.car_year_lists_xis the group’s id, the key you’ll use to read the group later.button_titleis the label of the button that adds a new entry.- The inner
fieldsarray defines the sub-fields of each entry; here a single text field with the idmb_car_year_details_av. Add more sub-fields the same way.
Step 2: output the group values
In the template that displays the post, inside the Loop, load the metabox data and loop through the entries:
<?php
$meta_data = get_post_meta( get_the_ID(), 'mbhouse_project_meta', true );
$meta_groups = ! empty( $meta_data['car_year_lists_x'] ) ? $meta_data['car_year_lists_x'] : array();
?>
<?php if ( $meta_groups ) : ?>
<ul class="car-years">
<?php foreach ( $meta_groups as $meta_group ) : ?>
<li><?php echo esc_html( $meta_group['mb_car_year_details_av'] ?? '' ); ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>get_post_meta()withtruereturns the metabox array, and$meta_data['car_year_lists_x']is the group inside it.- The ternary line stores the entries in
$meta_groups, or an empty array if nothing has been saved, and theifskips the list in that case. The! empty()check also matters on PHP 8: for a post without saved data,get_post_meta()returns an empty string, and reading a key from a string is a fatal error. - Each
$meta_groupis one entry: an array keyed by sub-field id, so$meta_group['mb_car_year_details_av']holds that entry’s text. The?? ''prints nothing, instead of a warning, for an entry without that value. esc_html()escapes each value. Change the list markup to whatever your design needs.get_the_ID()needs the Loop. Outside it, use the ID of the post you want, or$post->IDwith the global$post.
What does the saved group data look like?
While you build the template, print_r( $meta_data ) shows the structure. With two entries, the metabox above returns:
Array
(
[car_year_lists_x] => Array
(
[0] => Array
(
[mb_car_year_details_av] => Toyota Corolla 2021
)
[1] => Array
(
[mb_car_year_details_av] => Honda Civic 2023
)
)
)If the metabox is created with 'data_type' => 'unserialize', every field is saved under its own id instead, and get_post_meta( get_the_ID(), 'car_year_lists_x', true ) returns the list of entries directly.
Codestar Framework 1.x (metabox.config.php)
On a 1.x site, the group goes in the fields array of a metabox section in the framework’s config/metabox.config.php file:
$options[] = array(
'id' => 'mbhouse_project_meta',
'title' => 'Project Details',
'post_type' => 'post',
'context' => 'normal',
'priority' => 'default',
'sections' => array(
array(
'name' => 'availability',
'title' => 'Availability',
'fields' => array(
array(
'id' => 'car_year_lists_x',
'type' => 'group',
'title' => 'Year Data',
'desc' => 'Add availability for cars',
'button_title' => 'Add New Year',
'fields' => array(
array(
'id' => 'mb_car_year_details_av',
'type' => 'text',
'title' => 'Car Model & Year',
),
),
),
),
),
),
);
CSFramework_Metabox::instance( $options );Version 1.x stores the group the same way, as a list of entries under the group id inside the metabox array, so the template code from Step 2 outputs 1.x data unchanged.

