Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Fieldtype Matrix Laravel Package

ibexa/fieldtype-matrix

Matrix Field Type for Ibexa DXP and Ibexa Open Source adds configurable matrix fields to content types, letting editors define rows and columns of data. Licensed under Ibexa BUL or GPLv2.

View on GitHub
Deep Wiki
Context7

Getting Started

Prerequisites: Ibexa DXP (or Ibexa OSS) 4.x with the admin UI, Composer, and an ibexa/* version constraint already pinned. The package tracks Ibexa's release train (the latest release date matches DXP releases), so match it to your platform version rather than pulling dev-master.

composer require ibexa/fieldtype-matrix

Register the bundle. Locate the bundle class under src/bundle/ and add it to config/bundles.php (or app/AppKernel.php on older skeletons). Ibexa's own bundles usually auto-register through the Flex recipe — if the Matrix field type does not appear in the Content Types UI, bundle registration is the first thing to verify.

Where to look first. The README contains only license text, so read the source in this order:

  1. src/lib/FieldType/Matrix.php (or src/FieldType/) — the FieldType implementation: getFieldTypeIdentifier(), validate(), isEmpty(), toHash()/fromHash(), toPersistenceValue()/fromPersistenceValue().
  2. The Value object under FieldType/Matrix/Value.php — the class you actually touch from PHP and Twig.
  3. The Type class and its settings schema — content-type-level configuration (columns/labels). This is where the real design decisions live.
  4. src/bundle/Resources/config/*.yml — service ids, the ibexa.field_type tag, and the field type identifier string you pass to FieldTypeService.
  5. src/bundle/Resources/views/ — reference Twig rendering.
  6. tests/ — the most reliable documentation available for the value hash shape and settings arrays.

First use case. In admin, go to Content Types → your type → Add field definition → Matrix. Configure the columns/labels in the field definition settings, save, then edit a content item and fill in the cells. Render it with a nested loop. That round trip — define, edit, render — validates the install; everything after that is integration work.

Implementation Patterns

Defining the field in code (fixtures, install scripts, migrations) is a normal field definition plus a settings array. There is no published schema, so create the field once in admin and dump the resulting settings as your template:

$contentType->addFieldDefinition(
    $contentTypeService->newFieldDefinitionCreateStruct('specs', 'ibexa_matrix') // confirm identifier in bundle config
);
$fieldDefinition->fieldSettings = [/* copy from admin export or Type::getSettingsSchema() */];

Reading in PHP — always go through the value object, never the raw attribute value:

$value = $content->getFieldValue('specs');

if (!$value->isEmpty()) {
    foreach ($value->getMatrix() as $rowKey => $row) {
        // $row is typically array<string, mixed> keyed by column identifier
    }
}

Check the shipped Value class for the exact accessor; toHash() gives you the serialized form for exports and imports.

Rendering in Twig — treat it as a plain 2D structure and guard for empty:

{% set matrix = ez_field_value(content, 'specs') %}
{% if not matrix.isEmpty() %}
  <table>
  {% for rowKey, row in matrix.matrix %}
    <tr>
    {% for columnKey, cell in row %}
      <td>{{ cell }}</td>
    {% endfor %}
    </tr>
  {% endfor %}
  </table>
{% endif %}

Writing and updating — always via a draft, then publish. Matrix edits are content changes and go through normal versioning:

$draft = $contentService->createContentDraft($contentInfo);
$draft->getVersionInfo()->getContent()->setFieldValue('specs', $newValue);
$contentService->publishVersion($draft->getVersionInfo());

For bulk import, build the value with the field type's hash form (fromHash()) instead of hand-constructing the value object — the hash is the stable contract between persistence and the public API.

Integration tips

  • Wrap matrix reads in a small view model or DTO in your application layer. The Value shape is an implementation detail of a low-adoption package; isolating it means a version bump touches one class instead of every template.
  • Expect to write a GraphQL schema mapper if the matrix must be exposed via GraphQL — field types do not get types for free. Same for a custom Nameable if you want content names derived from matrix cells.
  • Confirm the field is Indexable and decide fulltext vs. identifier. After changing field settings, reindex with bin/console ibexa:reindex.
  • Use it for genuinely tabular, editor-maintained data: spec tables, rate cards, comparison grids. It is not a substitute for relations or a Collection field when rows need their own content identity, URLs, or permissions.

Gotchas and Tips

  • The license is the biggest gotcha. Dual Ibexa BUL / GPL-2, reported to Packagist as NOASSERTION. GPL-2 is widely treated as incompatible with distribution inside closed-source products, and the BUL branch requires an active DXP subscription. Clear this before the field type becomes load-bearing — license scanners will flag it and some CI policies will fail the build.
  • Dual licensing means no community safety net. 4 stars, 0 dependents, no third-party write-ups. Pin the version, read the changelog on every bump, and treat minor releases as potentially breaking on the value hash.
  • No usage docs. tests/ is your API reference. When debugging, start from the FieldType test fixtures — they show the exact settings and value arrays the code expects.
  • Settings are effectively frozen once content exists. Changing column definitions on a field definition with existing content is the classic way to produce rows that no longer align with headers. Plan the matrix schema up front; for real changes, add a new field and migrate data across.
  • Admin UI assets. Ibexa field editors are React widgets compiled into the admin UI. If the field renders as a bare textarea or nothing, check that the bundle's Resources/public build (or encore/yarn output) matches your admin UI version — version skew between admin UI and field type is a common failure.
  • Empty vs. missing, and required fields. isEmpty() plus validator configuration decide whether publishing is blocked. If you get a confusing publish error, look at the validator constraints in Resources/config — they are declared there, not in PHP.
  • Debugging checklist. bin/console debug:container --tag=ibexa.field_type | grep -i matrix to confirm registration; debug:container on the field type service to confirm it compiles; clear cache after config changes; watch var/log for exceptions thrown inside toPersistenceValue.
  • Extension points are thin. You can subclass the field type or Type, decorate the storage gateway, or swap the form mapper — but you inherit the maintenance burden of a single-vendor package with no downstream ecosystem. Prefer composition (wrap, don't extend) at your application boundary.
  • Translations. Field-level translation covers the whole matrix; do not assume per-cell localized values. Verify with getFieldValue() in a non-main language before designing a multilingual grid around it.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings