-
Notifications
You must be signed in to change notification settings - Fork 0
Using repeatable groups
The Simple Meta Boxes class enables you to group several fields into a repeatable group. Repeatable groups are convenient in cases that require the same couple of fields to appear together in a repeatable manner for an undefined number of times inside a post/page. A repeatable group will allow you to duplicate an entire group, as opposed to a repeater field, which only duplicates one specific field.
By adding the repeater_group
key to a metabox all the fields in that respective metabox will become a repeatable group. The value of repeater_group
should be an array. The array can be empty, but you can also pass it several optional keys (arguments):
title - String. Optional. The titles for the group items. The default title is "group".
numbering - Boolean. Optional. Used to denote whether or not the group titles should be numbered. Defaults to TRUE.
numbering_prefix - String. Optional. Allows you to specify the prefix that comes before the group title number. Default to an empty string. This argument will be ignored if the numbering arguments is set to FALSE.
Lets create a group together. This group will be used on a "contact us" template and enable the end-user to specify contact details for different people. The group will only appear on the "contact us" template and will have the following fields: name, phone number and email.
$metaboxes['contact_us_fields'] = array(
'id' => 'contact_us_fields',
'title' => 'Contacts List',
'page_templates' => array( 'page-contact-us.php' ),
'repeater_group' => array(
'title' => 'Contact Person',
'numbering_prefix' => '#',
),
'fields' => array(
array(
'title' => 'Name',
'id' => 'name',
'type' => 'text',
),
array(
'title' => 'Phone',
'id' => 'phone',
'type' => 'text',
),
array(
'title' => 'Email',
'id' => 'email',
'type' => 'email',
),
)
);
Repeater groups allow you to visually bundle meta fields together inside the Wordpress GUI, but under the hood each meta field in the group is still individually saved under its own id. This means that you can use these fields without the need to handle the entire group. On the other hand it also means they are not bundles together in a code-friendly manner. However, you can handle them as a group by creating a for
loop. When a group is saved Simple Meta Boxes will create an iterator meta key for it. This meta key inherits the meta box's key name and stores the number of items in said group as a string. Using this key we can iterate over the individual group meta field arrays, essentially treating them as a group. The following example uses the contact_us_fields
group that we created earlier and outputs the name, phone and email for each item in the group.
//Retrieve all the meta field arrays as well as the group iterator
$post_id = get_the_ID();
$name = get_post_meta( $post_id, 'name', TRUE );
$phone = get_post_meta( $post_id, 'phone', TRUE );
$email = get_post_meta( $post_id, 'email', TRUE );
$groupIterator = (int)get_post_meta( $post_id, 'contact_us_fields', TRUE );
//Iterate over the group items
for ($i = 0 ; $i < $groupIterator; $i++)
{
echo isset($name[$i])? $name[$i]: '';
echo isset($phone[$i])? $phone[$i]: '';
echo isset($email[$i])? $email[$i]: '';
}
This is a very simple example without any HTML formatting but it nonetheless shows how to iterate on a group. There are three important things to note regarding this example:
- Since meta keys are always saved as strings this example uses type casting to ensure that the group iterator (in this case
$groupIterator
) will be a valid integer. -
isset
is being used while accessing meta field keys to prevent cases in which some fields in the group might not exist. To prevent server errors it is recommended not to skip this vital step. - Although not shown in this example it is always a good idea to escape the meta key values before echoing them.
The example above is serviceable, but this method could add many lines of code to projects that make use of multiple repeatable groups. To simplify things add this neat helper function to functions.php
:
/**
* Retrieves a repeater group as a multidimentional array.
* Meta fields that exist but are missing specific items will have boolean FALSE as the value for those items.
* @param String $groupName The key (id) used for this group.
* @param Array $groupFields The meta keys (ids) of all the individual meta fields in this group.
* @return Mixed A multidimentional array with all the group fields or boolean FALSE if the function failed.
**/
function smb_get_group($groupName = FALSE, $groupFields = FALSE)
{
if ( !$groupName || !$groupFields ) return FALSE;
if ( !isset($post) ) global $post;
$groupIterator = $post->$groupName;
if ( !$groupIterator || ($groupIterator == '') || !is_numeric($groupIterator) ) return FALSE;
foreach ($groupFields as $field)
{
//The retrieval attemp of a falsy meta key will return the entire post's meta keys array and we DO NOT want that.
if ($field == FALSE)
{
if( ($key = array_search($field, $groupFields)) !== FALSE ) unset($groupFields[$key]);
continue;
}
${$field} = $post->$field;
//If the field does not exist remove it from the group.
if ( !${$field} || !is_array(${$field}) )
{
if(($key = array_search($field, $groupFields)) !== false) unset($groupFields[$key]);
}
}
//Create the group array.
$group = array();
for ($i=0; $i < $groupIterator ; $i++)
{
foreach ($groupFields as $field) {
$group[$i][$field] = (isset(${$field}[$i]))? ${$field}[$i]:FALSE;
}
}
return $group;
}
Call this function whenever you need to retrieve a group and you'll get the entire array-formatted group in one line:
$contactList = smb_get_group('contact_us_fields', array('name', 'phone', 'email'));