FieldtypeRepeaterMatrix
Stores a collection of repeating groups of fields where each item can be one of several configurable types
Extends FieldtypeRepeater — all Repeater features apply. Each item is a
RepeaterMatrixPage (extends RepeaterPage, extends Page), and the collection is a
RepeaterMatrixPageArray (extends RepeaterPageArray, extends PageArray). Items are stored as
real pages in the ProcessWire admin page tree under page/repeaters/.
RepeaterMatrixPageArray (extends RepeaterPageArray, extends PageArray). Each item is a
RepeaterMatrixPage (extends RepeaterPage, extends Page). Each item has a matrix type — an
integer stored in a system field called repeater_matrix_type — that determines which sub-fields
are available on it.
When output formatting is on (default), only published/visible items are returned.
When off ($page->of(false)), all items including unpublished/hidden "ready" items are included.
// Iterate items
foreach($page->matrix_field as $item) {
echo $item->type; // matrix type name (string)
echo $item->matrix('n'); // matrix type number (int)
echo $item->some_field; // sub-field value for this item's type
}
// Check if populated
if($page->matrix_field->count()) { ... }
// Get first item
$first = $page->matrix_field->first();
// Get item by index (0-based)
$item = $page->matrix_field->eq(0);
// Add a new item (specify type name or number)
$item = $page->matrix_field->getNewItem('type-name');
$item->title = 'New item';
$item->save();
$page->save('matrix_field');
// Add an item and set type afterwards
$item = $page->matrix_field->getNewItem();
$item->setMatrixType('type-name'); // or pass type number: setMatrixType(2)
$item->save();
$page->save('matrix_field');
// Remove an item
$page->matrix_field->remove($item);
$page->save('matrix_field');
// Get the owner page and field from a matrix item
$ownerPage = $item->getForPage();
$ownerField = $item->getForField();// Always turn off output formatting when manipulating items
$page->of(false);
// Add a new item of a specific type
$item = $page->matrix_field->getNewItem('type-name'); // by type name
$item = $page->matrix_field->getNewItem(2); // by type number
$item->title = 'Hello';
$item->save();
$page->save('matrix_field'); // saves item order, count, and membership
// Remove an item
$page->matrix_field->remove($item);
$page->save('matrix_field');
// Change the type of an existing item
$item = $page->matrix_field->first();
$item->setMatrixType('new-type-name'); // or by number: setMatrixType(2)
$item->save();
// Unpublish an item (excludes it from formatted output, keeps it in unformatted output)
$item->addStatus(Page::statusUnpublished);
$item->save();
// Re-publish a previously unpublished item
$item->removeStatus(Page::statusUnpublished);
$item->save();
// Reorder items: manipulate the PageArray, then save the parent page
// The order of the RepeaterMatrixPageArray is what determines saved order.
$page->of(false);
$items = $page->matrix_field;
$itemA = $items->first();
$itemB = $items->last();
$items->append($itemA); // move first item to end
$items->prepend($itemB); // move last item to beginning
$items->insertBefore($itemA, $itemB); // move $itemA to just before $itemB
$items->insertAfter($itemA, $itemB); // move $itemA to just after $itemB
$items->reverse(); // reverse the order of all items
$items->sort('title'); // sort items by a sub-field value
$page->save('matrix_field'); // persists the new order
// Add multiple items, then save the parent page once at the end
$items = [
[ 'type' => 'banner', 'title' => 'Top banner' ],
[ 'type' => 'text', 'body' => '<p>Hello</p>' ],
];
foreach($items as $data) {
$type = $data['type'];
unset($data['type']);
$item = $page->matrix_field->getNewItem($type);
foreach($data as $key => $value) $item->set($key, $value);
$item->save();
}
$page->save('matrix_field');Save workflow:
$item->save()writes the item's field values to the database.$page->save('matrix_field')updates the parent page's field record (item order, count, and which items belong to it). Both calls are required when adding items; only$item->save()is needed for in-place edits to an existing item.
The type on each item controls which sub-fields are available. Access type info from an item:
// Get type name (string) — all three are equivalent
$typeName = $item->type;
$typeName = $item->getMatrixType();
$typeName = $item->matrix('name');
// Get type number (int)
$typeN = $item->getMatrixType(true); // pass true to get number instead of name
$typeN = $item->matrix('n');
$typeN = $item->repeater_matrix_type; // direct access to the type field value
// Get the type label (localized to user language in multi-language installs)
$label = $item->getMatrixLabel();
$label = $item->matrix('label');
// Get fields available for this item's type (FieldsArray)
$fields = $item->getFields();
$fields = $item->matrix('fields');
// Check if a field is valid for this item's type
if($item->hasField('some_field')) { ... }
// Get a full info array for this item
$info = $item->getMatrixInfo();
// Includes: n, id, type, sort, label, status, fields, context, forPage, forField
// Also per-language labels (label1234 etc.) in multi-language installsAccessing type information from the field (RepeaterMatrixField):
/** @var RepeaterMatrixField $field */
$field = $wire->fields->get('matrix_field');
// Get all types as [ typeName => typeNumber ]
$types = $field->getMatrixTypes(); // e.g. [ 'banner' => 1, 'text' => 2, 'gallery' => 3 ]
// Get type number from name, or false if not found
$n = $field->getMatrixTypeByName('banner'); // 1
// Get type name from number, or false if not found
$name = $field->getMatrixTypeName(1); // 'banner'
// Get the label for a type (by name or number), localized to user language
$label = $field->getMatrixTypeLabel('banner');
$label = $field->getMatrixTypeLabel(1); // same, by number
// Get verbose info for all types, indexed by name
$info = $field->getMatrixTypesInfo();
/*
[
'banner' => [
'type' => 1,
'name' => 'banner',
'label' => 'Banner',
'prefix' => 'matrix1_',
'sort' => 0,
'head' => '',
'file' => '/path/to/site/templates/fields/matrix_field/banner.php',
'field' => RepeaterMatrixField,
'fields' => [ 'title' => Field, 'image' => Field ],
'fieldIDs' => [ 123, 456 ],
],
...
]
*/
// Get verbose info for a single type (by name or number)
$info = $field->getMatrixTypesInfo([ 'type' => 'banner' ]);
// Get a single property for all types
$labels = $field->getMatrixTypesInfo([ 'get' => 'label' ]); // [ 'banner' => 'Banner', ... ]
// Index by type number instead of name
$info = $field->getMatrixTypesInfo([ 'index' => 'type' ]); // [ 1 => [...], 2 => [...] ]$fields = $wire->fields;
$templates = $wire->templates;
// 1. Create and save the repeater matrix field
/** @var RepeaterMatrixField $field */
$field = $fields->new('RepeaterMatrix', 'my_matrix', 'My Matrix');
// 2. Get/create the field's internal template and fieldgroup
$fieldgroup = $field->getRepeaterFieldgroup();
// 3. Add ALL sub-fields (for all types) to the repeater's fieldgroup
$fieldgroup->add('title');
$fieldgroup->add('image');
$fieldgroup->add('body');
$fieldgroup->save();
// 4. Define matrix types (field names, IDs, or Field objects accepted in 'fields')
$field->addMatrixType('banner', [
'label' => 'Banner',
'fields' => [ 'title', 'image' ],
]);
$field->addMatrixType('text', [
'label' => 'Text Block',
'fields' => [ 'title', 'body' ],
]);
$field->save();
// 5. Add the field to your template
$template = $templates->get('your-template');
$template->fieldgroup->add($field);
$template->fieldgroup->save();Notes on programmatic creation:
- All sub-fields across all types must be added to the fieldgroup (step 3) first. The per-type
fieldsarrays in step 4 are subsets of those. addMatrixType($name, $options)accepts the following options:label(string): human-readable label shown in the editor (defaults toucfirst($name)).fields(array): field names, IDs, or Field objects for this type.sort(int): sort order in the add-item UI (auto-increments if omitted).head(string): item header format string in the editor. Supports{field_name}placeholders,icon-{name}for a FontAwesome icon, and#rrggbbfor a color accent.
- Throws
WireExceptionif the name is empty or already in use. The field must be saved after callingaddMatrixType()to commit the type definition to the database.
Supports all selectors from FieldtypeRepeater, plus matrix type filtering:
// Has at least one item
$pages->find('matrix_field.count>0');
// Has no items
$pages->find('matrix_field.count=0');
// Match by matrix type name (auto-converted to integer internally)
$pages->find('matrix_field.type=banner');
$pages->find('matrix_field.type!=banner');
// Match by matrix type number
$pages->find('matrix_field.repeater_matrix_type=1');
// Match by a sub-field value
$pages->find('matrix_field.title*=keyword');
$pages->find('matrix_field.some_field=value');
$pages->find('matrix_field.some_date>2024-01-01');Subfield matching performs an internal
$pages->find()on the repeater template, then checks which pages reference those results. This is powerful but can be slower on large datasets. Type matching (type=name) is handled natively and does not carry this overhead.
// Iterate and output manually, branching on type
// This is the most common strategy for outputting matrix fields
foreach($page->matrix_field as $item) {
if($item->type === 'banner') {
echo "<div class='banner'>{$item->headline}</div>";
} else if($item->type === 'text') {
echo "<div class='text'>{$item->body}</div>";
}
}
// Render via PHP render files
// Primary path: site/templates/fields/{template_name}/{field_name}/{type_name}.php
// Fallback path: site/templates/fields/{field_name}/{type_name}.php
// In the render file, $page is the RepeaterMatrixPage item.
foreach($page->matrix_field as $item) {
echo $item->render();
}
// Render just one sub-field (delegates to Page::renderField())
echo $item->render('body');
// Render a sub-field using a specific file
echo $item->render('body', '/path/to/file.php');
// Template syntax using each()
echo $page->matrix_field->each(function($item) {
return $item->render();
});
// Using each with string and {placeholders}
echo $page->matrix_field->each('<h3>{title}</h3><p>{summary}</p>');- Extends
FieldtypeRepeater:depth, lazy parents, ready items,getForPage(),getForPageRoot(),getForField(),getForFieldRoot(), andrepeaterLoading/repeaterCollapsesettings all apply. Note:repeaterLoading = loadingOffis not supported and falls back toloadingNew. - Items are stored as real pages under
/admin-url/page/repeaters/. Each matrix field gets a dedicated parent page and template. The template always includes therepeater_matrix_typesystem field. - Each item's type is stored as an integer in the
repeater_matrix_typesystem field.$item->typereturns the type name string as a shortcut. getNewItem($type): accepts an optional type name or number. Recycles existing ready items rather than always creating new pages. Call$item->save()then$page->save('field_name').allowChangeTypesetting (int): 0 = type locked after creation, 1 = type changeable (no "none/undefined"), 2 = type changeable including "none/undefined" (default=2).addTypeconstants (how the add-item UI works in the page editor):InputfieldRepeaterMatrix::addTypeSelect(0) — dropdown select (default)InputfieldRepeaterMatrix::addTypeLinks(1) — link per typeInputfieldRepeaterMatrix::addTypeImages(2) — image thumbnail per typeInputfieldRepeaterMatrix::addTypeCustom(3) — custom markup (hookable viarenderAddMatrixCustom)
- Type label groups: a label like
"Layout > Banner"splits into group"Layout"and type label"Banner". Groups appear as<optgroup>entries in the add-type select and are accessible as$item->matrix('groupLabel'). repeaterLoadingconstants (fromFieldtypeRepeater):FieldtypeRepeater::loadingNew(0) — ajax-load newly added items onlyFieldtypeRepeater::loadingAll(1) — ajax-load all items
repeaterCollapseconstants (fromFieldtypeRepeater):FieldtypeRepeater::collapseExisting(0) — collapse existing items (default)FieldtypeRepeater::collapseAll(1) — collapse all items including newFieldtypeRepeater::collapseNone(3) — do not collapse any items
- Database columns:
pages_id INT,data TEXT(CSV of item page IDs),count INT,parent_id INT— same asFieldtypeRepeater. - Compatible fieldtypes:
Fieldtypeand extending types only.Repeater Matrix
Please see the RepeaterMatrix Fieldtype for usage instructions. Click any linked item for full usage details and examples. Hookable methods are indicated with the icon. In addition to those shown below, the In addition to the methods and properties above, RepeaterMatrixField also inherits the methods and properties of these classes:RepeaterMatrixField is used instead of Field for fields of type FieldtypeRepeaterMatrixField class also inherits all the methods and properties of: RepeaterField, Field, WireData and Wire.Common
Properties
Name Return Summary RepeaterMatrixField::accordionMode int bool Use accordion mode where only 1 item open at a time? RepeaterMatrixField::addType int Method user uses to add items, see InputfieldRepeaterMatrix::addType constants. RepeaterMatrixField::allowChangeType bool int Allow changing types of existing repeater items? RepeaterMatrixField::allowMatrixTypes array Matrix types to allow when adding new (array of matrix type numbers) or empty to allow all. RepeaterMatrixField::familyFriendly bool int Use family friendly depth? Maintains expected parent/child relationships. RepeaterMatrixField::imageDefs string RepeaterMatrixField::imageStyle string RepeaterMatrixField::imageText bool int Show text labels with images? RepeaterMatrixField::lazyParents int bool Avoid creating parents when there are no items to store? RepeaterMatrixField::matrix1_fields array RepeaterMatrixField::matrix1_head string RepeaterMatrixField::matrix1_label string RepeaterMatrixField::matrix1_name string RepeaterMatrixField::matrix1_sort int RepeaterMatrixField::matrix2_fields array RepeaterMatrixField::matrix2_head string RepeaterMatrixField::matrix2_label string RepeaterMatrixField::matrix2_name string RepeaterMatrixField::matrix2_sort int RepeaterMatrixField::matrix3_fields array RepeaterMatrixField::matrix3_head string RepeaterMatrixField::matrix3_label string RepeaterMatrixField::matrix3_name string RepeaterMatrixField::matrix3_sort int RepeaterMatrixField::parent_id int Parent page ID for repeater items. RepeaterMatrixField::rememberOpen int bool Remember which items are open between requests? RepeaterMatrixField::repeaterAddLabel string Label to use for adding new items. RepeaterMatrixField::repeaterCollapse int Item collapse state, see FieldtypeRepeater::collapse* constants RepeaterMatrixField::repeaterDepth int string Max allowed depth for repeater items. RepeaterMatrixField::repeaterFields array Array of field IDs used in repeater. RepeaterMatrixField::repeaterLoading int Dynamic loading (ajax) in editor, see FieldypeRepeater::loading* constants. RepeaterMatrixField::repeaterMaxItems int Maximum number of items allowed. RepeaterMatrixField::repeaterMinItems int Minimum number of items allowed. RepeaterMatrixField::repeaterReadyItems int (deprecated) RepeaterMatrixField::repeaterTitle string Field name to use for repeater item labels or format string with {fields}. RepeaterMatrixField::template_id int Template ID used by repeater items. RepeaterMatrixField::type Fieldtype Additional methods and properties
API reference based on ProcessWire core version 3.0.259