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

Repeatering Field Type Laravel Package

newebtime/repeatering-field_type

Repeatering Field Type is a Laravel/PHP field type for repeatable form inputs, letting you add, reorder, and manage multiple grouped values within a single field. It simplifies structured content editing in admin panels and Streams-style applications.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a PyroCMS stream field type — not a standalone Laravel package. It only makes sense inside a PyroCMS application that already has the Streams platform (anomaly/streams-platform) installed.

  1. Install into the addon path. Composer installation may work if the repo publishes a proper composer.json type of pyrocms-module/addon, but with zero stars and zero dependents the safest route is dropping it into addons/{vendor}/repeatering-field_type/ (or ./addons/default/... depending on your multi-site layout) and registering it.
  2. Register/install the addon.
    php artisan addon:install newebtime.field_type.repeatering
    
    Then confirm the field type appears under Addons → Field Types in the control panel.
  3. Where to look first:
    • src/RepeateringFieldType.php — the FieldType class; check getInputView(), getOutputView(), getWrapperView(), and getConfigurationView() to see how it wires up sub-fields.
    • resources/views/ — the input partial used in forms and the output partial used in templates.
    • resources/lang/ — labels and config text.
    • src/RepeateringFieldTypePresenter.php (if present) — the presenter is what you actually call from templates, so read this before writing any markup.
  4. First use case: add a field to a stream (e.g. a pages stream) with type Repeatering, then define one or more sub-fields (label + value pairs, or sub-field slugs) in the field's configuration. The canonical use case is a page with a variable list of rows — FAQs, feature cards, footer links, timeline entries — where you don't want a whole separate stream per row.

Validate with a trivial page first: add one text sub-field, save two rows, and dump the raw value in a Blade/Twig view to see the storage shape before building anything real.

Implementation Patterns

Field configuration drives the schema. Unlike a simple text field, a repeater's behaviour is defined by its field config (the sub-fields/columns). Treat that config as a mini-migration: it is serialized and stored per-field, so changing it later does not reshape existing data. Decide your sub-fields up front, or write a data-normalisation routine when you change them.

Reading values in templates. The field returns a collection of row objects/arrays. Typical access looks like:

@foreach($entry->faq_items as $item)
    <dt>{{ $item->question }}</dt>
    <dd>{{ $item->answer }}</dd>
@endforeach

If $item is a plain array you'll need $item['question']. Check the presenter's __get/offsetGet to know which you get — it varies between field types. Dump $entry->faq_items once in a dev view and never guess again.

Writing values programmatically. When seeding or mutating from a service, build the payload as an array of associative arrays keyed by sub-field slug, then save the entry through the normal Streams repository ($entries->save($entry)). Don't write raw JSON into the column unless you also handle the field type's expected encoding — round-trip through the model so the field type runs its transformation.

Pairing with stream forms. Because the input view renders its own repeatable row markup, it composes well inside a form field type. If you build custom CP UI, reuse the addon's own input partial rather than reimplementing row add/remove, otherwise your markup will drift from the field's expected input payload (field_slug[row_index][sub_field_slug] style keys).

Common integrations:

  • Layouts/partials — pull the repeater out of the entry and pass it to a partial so the markup is reused across pages.
  • API/resource endpoints — cast to array before returning; the underlying value is usually JSON, so JSON-encode carefully if you're already inside a JSON response.
  • Relationship + repeater — repeaters are commonly used to hold a pair (e.g. an image + caption), while the real entity lives in its own stream. For anything you need to query or filter on, use a separate stream and relate it; keep the repeater for dumb display data.

Migration pattern for new fields:

$field = $fields->create([
    'slug'     => 'faq_items',
    'type'     => 'anomaly.field_type.repeatering',
    'name'     => 'FAQ Items',
    'config'   => [
        // sub-field definitions per the addon's config schema
    ],
]);
$assignment = $assignments->create([...]);

Gotchas and Tips

Storage is opaque. Repeater values are almost certainly stored as JSON (or a serialized blob) in a single text/longtext column. That means: no SQL search across sub-fields, no indexing, no aggregate queries, and WHERE clauses are useless. If you need to search or sort by a sub-field, promote it to a real column or a related stream.

Size limits bite. MySQL TEXT caps at 64KB. A repeater with many rows and long fields will silently truncate or error. Confirm the migration uses longText, and if you control the migration, make it one.

Config changes don't migrate data. Adding/removing/renaming a sub-field leaves old rows with stale keys. Write a one-off artisan command to walk entries and normalise. There's no built-in versioning.

Nesting is risky. Do not assume the repeater can contain another repeater. Check the input view's row template — if it only renders scalar field types, nesting will either fail or produce unusable input names. For nested structures, use two levels of streams/relationships instead.

Validation is per-field, not per-sub-field. Required/validation rules on sub-fields may not surface as form validation errors. Add server-side validation in your controller or a form request handler, and remember to sanitise before rendering (sub-field values are user input).

Debugging checklist: dump the raw model attribute ($entry->getAttribute('faq_items')) versus the presenter access ($entry->faq_items). Half the "it's empty" reports are a presenter returning a Collection you're not iterating, or an entry not being re-fetched after save.

Extension points:

  • Override the addon's views by publishing/copying into your theme's view namespace rather than editing vendor files.
  • Extend RepeateringFieldType and register your own field type if you need custom validation or a different storage format.
  • Use the presenter's __call/accessor overrides for custom output helpers (e.g. a toUl() method).

Bus factor is 1. Zero stars, zero dependents, single vendor on GitLab. Pin the exact commit in your composer.json (or vendor the addon into addons/), and add a smoke test that saves and re-reads a two-row entry so an accidental upgrade doesn't quietly break production content. If the addon is abandoned, the migration path is: read the JSON column directly, normalise to a dedicated stream, and drop the field.

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.
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log