ProcessWire Matrix Type Module
A ProcessWire module for managing and displaying typed repeater matrix items with structured data extraction and flexible rendering.
Author: Maxim Semenov — maxim@smnv.org — smnv.org
Version: 1.0.9
Repository: github.com/mxmsmnv/InputfieldMatrixType
License: MIT
The Problem
When working with ProcessWire's Repeater Matrix fields, identifying the type of each matrix item on the frontend is not straightforward:
- No built-in field exists to store human-readable type identifiers
- Extracting structured data from different matrix types requires repetitive code
- Creating JSON APIs or dynamic frontends becomes unnecessarily complicated
This module solves these problems by providing a dedicated fieldtype for storing type identifiers and a data processor for consistent extraction.
Overview
- FieldtypeMatrixType — Custom fieldtype for storing matrix item type identifiers
- InputfieldMatrixType — Admin interface for configuring matrix types
- MatrixDataProcessor — PHP class for extracting and structuring matrix data
Features
- Define unique type identifiers for each matrix item
- Set human-readable display names
- Automatic data extraction from repeater matrix fields
- Structured output format (JSON-ready)
- Built-in price and SKU field support
- Support for multiple field types (text, images, options, pages, etc.)
- Skip empty values automatically
- Filter system fields automatically
- Reliable type detection via native
repeater_matrix_type+getMatrixTypes()
Installation
- Copy the module folder to
/site/modules/InputfieldMatrixType/ - Go to Admin → Modules → Refresh
- Install FieldtypeMatrixType — InputfieldMatrixType installs automatically as a dependency
Module Structure
/site/modules/InputfieldMatrixType/
├── FieldtypeMatrixType.module.php
├── InputfieldMatrixType.module.php
├── MatrixDataProcessor.php
└── README.mdSetup
Step 1 — Create identifier fields
For each matrix type, create a separate field of type Matrix Type (FieldtypeMatrixType).
Step 2 — Configure each identifier field
Go to Admin → Fields → [field name] → Details tab and fill in:
- Matrix Type Identifier — unique slug used in code (e.g.
box) - Display Name — human-readable label (e.g.
Box)
⚠ The Matrix Type Identifier is what
$item['type']returns in your template. It must match exactly what you use in your switch/if statements.
Step 3 — Add to matrix templates
In each matrix type template, add its corresponding identifier field. The field renders as a hidden input in the admin — no data entry needed from editors.
Usage
⚠ Namespace requirement
Template files must declare the namespace, otherwise new MatrixDataProcessor() will fail:
<?php namespace ProcessWire;Basic example
<?php namespace ProcessWire;
$processorPath = wire('config')->paths->siteModules . 'InputfieldMatrixType/MatrixDataProcessor.php';
if (file_exists($processorPath)) require_once $processorPath;
$processor = new MatrixDataProcessor($page);
$items = $processor->getItems('your_matrix_field_name');Use
wire('config')instead of$config— it works reliably in all template contexts.
Data structure returned
[
[
'id' => 1234,
'type' => 'sedan', // Matrix Type Identifier
'displayName' => 'Sedan', // Display Name
'sku' => 'VIN-001', // SKU field value if present
'price' => 24900.00, // Price field value if present
'fields' => [ // All non-system fields with values
[
'name' => 'make',
'label' => 'Make',
'type' => 'FieldtypeText',
'value' => 'Toyota'
],
[
'name' => 'year',
'label' => 'Year',
'type' => 'FieldtypeInteger',
'value' => 2022
],
[
'name' => 'transmission',
'label' => 'Transmission',
'type' => 'FieldtypeOptions',
'value' => ['Automatic']
],
[
'name' => 'all_wheel_drive',
'label' => 'All Wheel Drive',
'type' => 'FieldtypeCheckbox',
'value' => true
],
]
]
]Field value types
| ProcessWire fieldtype | PHP value returned |
|---|---|
| FieldtypeText / FieldtypeTextarea | string |
| FieldtypeInteger | int |
| FieldtypeFloat / FieldtypeDecimal | float |
| FieldtypeOptions | array of title strings, e.g. ['Red', 'Blue'] |
| FieldtypeCheckbox | bool |
| FieldtypePage | array with id, title, url — or array of such arrays |
| FieldtypeImage | array with url, description, width, height |
Empty values are skipped automatically — a field only appears in $item['fields'] if it has a non-empty value.
Examples
Case 1 — Real estate: Apartment, House, Land
Each property type has a completely different set of fields. Matrix field name: details
Identifier fields:
| Field name | Matrix Type Identifier | Display Name |
|---|---|---|
details_apartment | apartment | Apartment |
details_house | house | House |
details_land | land | Land |
Fields per type:
| Type | Fields |
|---|---|
| apartment | rooms (Integer), floor (Integer), floors_total (Integer), area_sqm (Float), bathroom_type (Options), balcony (Checkbox), elevator (Checkbox) |
| house | area_sqm (Float), land_area_sqm (Float), floors (Integer), garage (Checkbox), heating_type (Options) |
| land | land_area_sqm (Float), land_category (Options), electricity (Checkbox), gas (Checkbox), water (Checkbox) |
Template:
<?php namespace ProcessWire;
$processorPath = wire('config')->paths->siteModules . 'InputfieldMatrixType/MatrixDataProcessor.php';
if (file_exists($processorPath)) require_once $processorPath;
$processor = new MatrixDataProcessor($page);
$items = $processor->getItems('details');
foreach ($items as $item):
?>
<div data-type="<?= $item['type'] ?>">
<h3><?= $item['displayName'] ?></h3>
<?php foreach ($item['fields'] as $f): ?>
<?php
$val = $f['value'];
if (is_array($val)) $val = implode(', ', $val);
if (is_bool($val)) $val = $val ? 'Yes' : 'No';
if ($val === null || $val === '') continue;
?>
<div>
<span><?= htmlspecialchars($f['label']) ?></span>
<span><?= htmlspecialchars((string)$val) ?></span>
</div>
<?php endforeach ?>
</div>
<?php endforeach ?>Case 2 — Alcohol shop: Wine, Cognac, Beer
Each drink type has its own set of characteristics. Matrix field name: drinks
Identifier fields:
| Field name | Matrix Type Identifier | Display Name |
|---|---|---|
drinks_wine | wine | Wine |
drinks_cognac | cognac | Cognac |
drinks_beer | beer | Beer |
Fields per type:
| Type | Fields |
|---|---|
| wine | grape_variety (Options), vintage_year (Integer), region (Text), sweetness (Options: Dry / Semi-dry / Semi-sweet / Sweet), color (Options: Red / White / Rosé), volume_ml (Integer) |
| cognac | age_years (Integer), region (Text), distillery (Text), volume_ml (Integer) |
| beer | style (Options: Lager / Ale / Stout / IPA / Wheat), ibu (Integer), abv (Float), filtered (Checkbox), volume_ml (Integer) |
Template:
<?php namespace ProcessWire;
$processorPath = wire('config')->paths->siteModules . 'InputfieldMatrixType/MatrixDataProcessor.php';
if (file_exists($processorPath)) require_once $processorPath;
$processor = new MatrixDataProcessor($page);
$items = $processor->getItems('drinks');
foreach ($items as $item):
?>
<div data-type="<?= $item['type'] ?>">
<h3><?= $item['displayName'] ?></h3>
<?php if ($item['price']): ?>
<div>$<?= number_format($item['price'], 2) ?></div>
<?php endif ?>
<?php foreach ($item['fields'] as $f): ?>
<?php
$val = $f['value'];
if (is_array($val)) $val = implode(', ', $val);
if (is_bool($val)) $val = $val ? 'Yes' : 'No';
if ($val === null || $val === '') continue;
?>
<div>
<span><?= htmlspecialchars($f['label']) ?></span>
<span><?= htmlspecialchars((string)$val) ?></span>
</div>
<?php endforeach ?>
<button data-item-id="<?= $item['id'] ?>">Add to Cart</button>
</div>
<?php endforeach ?>Skip Fields
The processor automatically skips:
- System fields:
id,name,parent,template,created,modified,createdUser,modifiedUser repeater_matrix_typeprice,sku(returned separately at the item level)- All
FieldtypeMatrixTypefields (used for type detection only)
To customize, modify the $skipFields array in MatrixDataProcessor.php.
Custom Formatting
Override formatValue() to add support for custom fieldtypes:
protected function formatValue($value, $field) {
$fieldType = $field->type->className();
switch($fieldType) {
case 'YourCustomFieldtype':
return $this->formatCustom($value);
default:
return parent::formatValue($value, $field);
}
}API Reference
// Constructor
$processor = new MatrixDataProcessor(Page $page);
// Get all items from a matrix field
$items = $processor->getItems(string $matrixFieldName = 'matrix');Troubleshooting
Class "MatrixDataProcessor" not found
Add <?php namespace ProcessWire; at the top of your template file.
No items returned
- Verify the matrix field name:
$processor->getItems('your_field_name') - Check that items are published and the field has content
type returns "unknown"
- Ensure each matrix type template has a
FieldtypeMatrixTypefield added to it - Open the field in Admin → Fields → Details and fill in the Matrix Type Identifier
Requirements
- ProcessWire 3.0+
- PHP 8.1+
License
MIT — free to use and modify
Author: Maxim Semenov — maxim@smnv.org
Module Version: 1.0.9
More modules by Maxim Semenov
- Added 1 month ago by Maxim Semenov
Legal Docs
AI-powered legal document generator. Generates Privacy Policy, Terms of Use, Cookie Policy and more for 93 jurisdictions.4Added 3 weeks ago by Maxim SemenovPlausible Analytics
Plausible Analytics dashboard using Stats API v2 with page-edit widget, traffic trends chart, and geo/device tabs.4Added 2 months ago by Maxim Semenov- Added 4 weeks ago by Maxim Semenov
- Added 4 weeks ago by Maxim Semenov
Install and use modules at your own risk. Always have a site and database backup before installing new modules.