FieldtypeRepeaterMatrix class

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/.

Value type

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.

Getting and setting values
// 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();
Adding, removing, and saving items
// 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.

Matrix types

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 installs

Accessing 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 => [...] ]
Creating a repeater matrix field programmatically
$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 fields arrays in step 4 are subsets of those.
  • addMatrixType($name, $options) accepts the following options:
    • label (string): human-readable label shown in the editor (defaults to ucfirst($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 #rrggbb for a color accent.
  • Throws WireException if the name is empty or already in use. The field must be saved after calling addMatrixType() to commit the type definition to the database.
Selectors

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.

Output / markup
// 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>');
Notes
  • Extends FieldtypeRepeater: depth, lazy parents, ready items, getForPage(), getForPageRoot(), getForField(), getForFieldRoot(), and repeaterLoading/ repeaterCollapse settings all apply. Note: repeaterLoading = loadingOff is not supported and falls back to loadingNew.
  • 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 the repeater_matrix_type system field.
  • Each item's type is stored as an integer in the repeater_matrix_type system field. $item->type returns 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').
  • allowChangeType setting (int): 0 = type locked after creation, 1 = type changeable (no "none/undefined"), 2 = type changeable including "none/undefined" (default=2).
  • addType constants (how the add-item UI works in the page editor):
    • InputfieldRepeaterMatrix::addTypeSelect (0) — dropdown select (default)
    • InputfieldRepeaterMatrix::addTypeLinks (1) — link per type
    • InputfieldRepeaterMatrix::addTypeImages (2) — image thumbnail per type
    • InputfieldRepeaterMatrix::addTypeCustom (3) — custom markup (hookable via renderAddMatrixCustom)
  • 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').
  • repeaterLoading constants (from FieldtypeRepeater):
    • FieldtypeRepeater::loadingNew (0) — ajax-load newly added items only
    • FieldtypeRepeater::loadingAll (1) — ajax-load all items
  • repeaterCollapse constants (from FieldtypeRepeater):
    • FieldtypeRepeater::collapseExisting (0) — collapse existing items (default)
    • FieldtypeRepeater::collapseAll (1) — collapse all items including new
    • FieldtypeRepeater::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 as FieldtypeRepeater.
  • Compatible fieldtypes: FieldtypeRepeaterMatrix and extending types only.
API reference: methods, hooks

Click any linked item for full usage details and examples. Hookable methods are indicated with the icon. In addition to those shown below, the FieldtypeRepeaterMatrix class also inherits all the methods and properties of: FieldtypeRepeater, Fieldtype, WireData and Wire.

Show class?     Show args?       Only hookable?    

Common

NameReturnSummary 
FieldtypeRepeaterMatrix::exportConfigData(Field $field, array $data)
array

Export configuration values for external consumption

FieldtypeRepeaterMatrix::getAllMatrixTypesInfo()
array

Get verbose information array for all RepeaterMatrix fields in the system

 
FieldtypeRepeaterMatrix::getConfigInputfields(Field $field)
InputfieldWrapper

Return configuration fields definable for each FieldtypePage

FieldtypeRepeaterMatrix::getFieldClass()
string

Get class name to use Field objects of this type (must be class that extends Field class)

 
FieldtypeRepeaterMatrix::getMatchQuery($query, string $table, string $subfield, string $operator, string $value)
DatabaseQuerySelect PageFinderDatabaseQuerySelect

Update a DatabaseQuerySelect object to match a Page

 
FieldtypeRepeaterMatrix::getMatrixFields()
array Field

Get an array of all RepeaterMatrix fields

 
FieldtypeRepeaterMatrix::getMatrixTemplate($field)
Template

Return the repeater matrix template used by Field (same as getRepeaterTemplate except that it’s public)

 
FieldtypeRepeaterMatrix::getMatrixTypeByName(string $name)
bool int

Return matrix type (integer) for given name, or boolean false if not found

 
FieldtypeRepeaterMatrix::getMatrixTypeLabel($type)
string

Get the label for the given matrix type (name or number)

 
FieldtypeRepeaterMatrix::getMatrixTypeName(int $type)
string bool

Return matrix type name for given matrix type integer, or boolean false if not found

 
FieldtypeRepeaterMatrix::getMatrixTypes()
array

Return an array of just matrix types in format [ typeName => typeNumber ]

FieldtypeRepeaterMatrix::getMatrixTypesInfo()
array string null

Get all information available for each matrix type in an array of arrays indexed by type name

 
FieldtypeRepeaterMatrix::getMaxMatrixTypes(Field $field)
int

Get the max quantity of matrix types (highest 'n' value used by matrix type in $field)

 
FieldtypeRepeaterMatrix::getPageArrayClass()
string

Get the class used for repeater PageArray objects

 
FieldtypeRepeaterMatrix::getPageClass()
string

Get the class used for repeater Page objects

 
FieldtypeRepeaterMatrix::getRepeaterMatrixConfigHelper(Field $field)
FieldtypeRepeaterMatrixConfigHelper

@param Field $field

 
FieldtypeRepeaterMatrix::getSelectorInfo(Field $field)
array

Get information used by selectors for querying this field

FieldtypeRepeaterMatrix::importConfigData(Field $field, array $data)
array

Convert an array of exported data to a format that will be understood internally

FieldtypeRepeaterMatrix::wired()
None

API ready

 

Additional methods and properties

In addition to the methods and properties above, FieldtypeRepeaterMatrix also inherits the methods and properties of these classes:

API reference based on ProcessWire core version 3.0.259