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.
What it actually is. Despite the "Laravel/PHP package" framing, this is not a general-purpose Composer library. It is a Streams Platform addon — specifically a field type for anomaly/streams-platform, the addon framework underneath PyroCMS 3.x. It cannot be composer require'd into an arbitrary Laravel application and used on its own; it only has meaning once the Streams addon registry, field type base class, and stream/entry persistence layer are present. That distinction drives almost every conclusion below.
Architecture fit. The field type likely implements the Streams contract (getRelation(), getRules(), getView()/getModifier(), plus persistence hooks) to store a polymorphic reference as a {field}_type / {field}_id column pair and resolve it to the correct stream entry at render time. Architecturally this is the right shape for the problem — it mirrors Eloquent's morphTo. The concern is that the Streams field type API is not stable across major versions, and this package has not tracked any of those changes.
Integration feasibility: low. Signals are unambiguous and mutually reinforcing:
each/array_* semantics alone will break it.Technical risk. High on every axis: supply chain (unmaintained transitive dependency, no CVE monitoring, no security response path), correctness (no test suite visible, no CI), and data integrity (see polymorphic orphan risk under Operational Impact). There is also no maintainer to escalate to.
Key questions to resolve before any further spend:
anomaly/streams-platform version is pinned, and does a compatible install even resolve today?Verdict: Reject for new development. Conditional-accept only for an existing Streams install with live data, and only as a vendored, owned fork — never as an unmodified upstream dependency.
Stack fit. Two viable worlds, and the answer differs sharply:
morphTo/morphMany with a nullableMorphs() migration, a MorphTo select in your form layer (Filament, Nova, or a custom Livewire/Blade component with a type selector + searchable entry picker), and a Rule::exists() pair validated against the polymorphic type map. Reimplementing this package's behavior natively is a few hundred lines and gives you tests, typing, and a maintainer.Migration path (if Streams is the target).
composer.json for anomaly/streams-platform constraints and the addon's declared type. Attempt resolution in a throwaway branch; do not merge an attempted install into a shared branch.dev-master or 2015 tag floating in a production lockfile.composer.json constraints, fix removed helpers and signatures, verify the field type contract still matches the pinned Streams version (this is the step most likely to require a rewrite of the class rather than a patch).{field}_type / {field}_id columns and confirm all stored type values still map to registered streams.Compatibility. Assume broken until proven otherwise in a throwaway environment. Test matrix must include the exact PHP version, the exact Streams version, the addon install/upgrade path, and a full create-read-update-delete cycle through the field type — including rendering inside a Streams listing view, which is where polymorphic resolution most often degrades.
Sequencing. Do the requirement interrogation (key questions above) before the fork. If the requirement can be satisfied by a fixed set of two or three known stream references, a plain relation field or a small composite field is lower cost and lower risk than reviving this package. Reserve the polymorphic path for genuinely open-ended reference targets.
Maintenance. Effectively zero upstream. There will be no bug fixes, no PHP 8.x compatibility work, no dependency updates, and no release when Streams changes. Any adoption is a permanent in-house maintenance commitment, and the cost is front-loaded: the initial port is likely larger than the package itself.
Support. No maintainer, no issue triage, no security response. Internal SLAs must assume "we are the vendor." Budget for at least one engineer with hands-on Streams familiarity — a shrinking skill pool, which is itself a hiring and bus-factor risk.
Scaling. Polymorphic references defeat database-level referential integrity, so no foreign keys. Listing views that render this field must resolve morph targets per row; without explicit eager loading you get classic N+1 behavior that is invisible in development and painful at a few thousand rows. Any Streams query/criteria layer that doesn't understand morph eager loading will need custom handling or a denormalized cache column.
Failure modes to design for:
_id values that throw on render.exists rule cannot span tables; a missing custom rule permits references to non-existent entries that only fail at render time, i.e. in production, on read.Ramp-up. For a team already fluent in Streams addon conventions, roughly a day to orient and a sprint to port, test, and instrument. For a standard Laravel team with no Streams exposure, the onboarding cost of the platform dwarfs the package: weeks, for a capability that is a native Eloquent feature.
Recommendation. Decline adoption as a dependency. If the target stack is Streams and the requirement is real, fork it, own it, test it, and instrument it — and price that work honestly against just writing the relation natively. If the target stack is modern Laravel, this package should not appear in the dependency graph at all.
How can I help you explore Laravel packages today?