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

Polymorphic Field Type Laravel Package

anomaly/polymorphic-field_type

Polymorphic field type for the Streams platform that lets a single field reference records from multiple stream models, making relationships flexible and reusable across modules. A practical addition for Laravel projects built on Streams that need dynamic, multi-model references.

View on GitHub
Deep Wiki
Context7

Getting Started

Reality check before you install: this addon was last released in August 2015, sits at 0 stars, 0 dependents, and targets the Streams Platform as it existed around PyroCMS 3.0 / Laravel 5.1–5.2. It is effectively abandoned. Treat it as a reference implementation to read and copy rather than a dependency you ship to production on a modern stack.

Install (on a period-correct project):

composer require anomaly/polymorphic-field_type
php artisan addon:install anomaly/polymorphic_field_type

Because the package predates Laravel 5.5 package auto-discovery, you may need to register the service provider manually in config/app.php:

Anomaly\PolymorphicFieldType\PolymorphicFieldTypeServiceProvider::class,

Where to look first:

  1. src/PolymorphicFieldType.php — the field type class. This is where the column type, validation rules, form input, and value accessor live.
  2. src/PolymorphicFieldTypeServiceProvider.php — registration, routes, bindings, view namespaces.
  3. resources/config/config.php — the field type's configurable options (typically which streams are selectable). This tells you what you can actually put in a stream's field config.
  4. resources/views/ — the form input and any display partials you can override per-namespace.
  5. resources/lang/ — labels/placeholders, which tell you the intended UX vocabulary.

First use case: a "Related Content" field on a Pages stream where an editor can point at either a Blog Post or a Product. Create the field via the admin Streams UI (Fields → Add Field → choose the Polymorphic type), assign it to the stream, then confirm the generated column exists and the form renders before writing any code against it.

Implementation Patterns

Defining the field in a migration/repository. If you manage streams in code rather than through the admin, add the field in your stream migration and pass the addon type slug in snake_case (polymorphic) along with the config the field type expects:

$stream->addField('related', [
    'type'   => 'anomaly.field_type.polymorphic',
    'config' => [
        'streams' => ['posts', 'products'], // confirm key name against config.php
    ],
]);

Read resources/config/config.php before guessing config keys — there is no guaranteed schema documentation and the keys are whatever the 2015 author chose.

Reading values in your own code. Field types typically expose the resolved value through the entry's magic attribute. Always null-check and normalize, because a polymorphic field can legitimately hold zero, one, or many targets across heterogeneous streams:

$related = $entry->related; // may be an array, a collection, or null

foreach ((array) $related as $item) {
    // $item may be a Streams entry, an Eloquent model, or a raw id, depending on the implementation
    dump($item->getId(), $item->getStreamSlug());
}

Rendering in Twig (PyroCMS):

{% if entry.related is not empty %}
  <ul>
  {% for item in entry.related %}
    <li><a href="{{ item.route('view') }}">{{ item.title }}</a></li>
  {% endfor %}
  </ul>
{% endif %}

The value returned by a polymorphic field is not guaranteed to have a route('view'); guard per stream or render a generic link.

Saving from a custom form. If you bypass the Streams form builder, don't hand-roll the write. Use the field type's own handling path ($fieldType->setEntry($entry)->setValue($input), or simply save through the entry repository) so the storage format matches what the accessor expects. Writing raw ids into the column is the fastest way to produce a field that renders fine but reads as empty.

Integration tips:

  • Keep the field narrow. A field that can reference anything is unusable in a CMS UI; pair it with a small allow-list of streams and let a second field cover the rest.
  • Wrap consumption in a small presenter/view-model method ($entry->presenter()->relatedItems()) so the day the package is replaced, you only edit one class.
  • If you need polymorphic relations in your own Eloquent models, use Laravel's built-in morphTo / morphMany instead. That's a first-class, maintained feature and covers the same ground for model-level work.

Gotchas and Tips

  • It almost certainly will not run on Laravel 6+. Service providers, container bindings, and the FieldType base class API all changed after 2015. Expect fatal errors on install before you write a single line. Check composer.json for the actual illuminate/* and Streams version constraints.
  • No tests, no dependents, no maintenance. There is no safety net. Budget time to read the whole src/ directory — it's small enough to audit in twenty minutes, which is the right move.
  • Storage format is the hidden contract. Find out early whether the column holds serialized data, JSON, or delimited stream:id pairs. Everything downstream (queries, search, eager loading) depends on it, and there are no foreign keys protecting you from orphaned references when a target entry is deleted.
  • Orphaned references are your problem. Deleting a blog post will not clean up the polymorphic field on every entry pointing at it. Add a listener on entry deletion, or filter dangling references at render time.
  • N+1 queries. Resolving heterogeneous targets inside a loop is expensive by nature. Cache the presenter output, or pre-load the likely streams in your controller when building listings.
  • Admin UI filtering may be missing. In a 2015 addon, the dropdown often lists all streams regardless of the configured allow-list — that's a UI-only bug, so validate on save rather than trusting the form.
  • Empty vs. null. Test saving an empty selection and reading it back. Old field types frequently store '', '[]', or null inconsistently depending on the path taken.
  • Debugging workflow. After changing field type code, clear compiled assets and caches (php artisan view:clear, php artisan cache:clear, and the Streams compile command if present in your version). Stale compiled field type classes make it look like your edits did nothing.
  • Extension points. You can override the field type's views by publishing/placing them under your own namespace, and you can subclass PolymorphicFieldType to change validation or presentation. Given the package's age, subclassing is safer than editing vendor/ — but if you find yourself subclassing heavily, you've written the replacement already.
  • Verdict for day-to-day use: not advisable as a dependency. Use it as a design reference for Streams field types, and implement polymorphic content relationships with native Laravel morphTo relations or a purpose-built field type you control.
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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib