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

Addon Field Type Laravel Package

anomaly/addon-field_type

Anomaly Field Type is a Streams platform addon for Laravel that registers a reusable field type, helping developers extend Anomaly CMS forms and entry models with structured custom fields. It provides addon scaffolding for integrating field-type behavior into Streams-based applications.

View on GitHub
Deep Wiki
Context7

Getting Started

This field type ships as part of the standard Anomaly/PyroCMS Streams toolchain, so most projects already have it available transitively. Confirm with:

composer show anomaly/addon-field_type

If it is missing:

composer require anomaly/addon-field_type
php artisan addon:install anomaly.field_type.addon
php artisan addon:publish anomaly.field_type.addon

Where to look first, in order:

  1. src/AddonFieldType.php — the getOptions() method is the whole package; it reads the type config and maps the matching addon collection to a namespace => name array.
  2. config/config.php — exposes the single knob (type) that filters the dropdown.
  3. resources/views/input.twig — the control panel select; usually just form.select(...).

The canonical first use case: an admin-facing stream where a record needs to point at one of your installed addons (for example, "which module handles this integration?" or "which plugin owns this webhook?"). Rather than hardcoding namespaces in a config file, you declare the field:

$fields->addField('handler', [
    'type'   => 'anomaly.field_type.addon',
    'config' => ['type' => 'module'],
]);

You now have a dropdown in the form and a namespace string stored on the entry. That is the entire day-to-day surface area.

Implementation Patterns

Declaring in migrations. The normal path is inside a stream migration, using $fields->addField(). Always set config.type explicitly — the default is unfiltered and will dump every addon type into one list, which is rarely what you want:

$fields->addField('integration', [
    'type'   => 'anomaly.field_type.addon',
    'config' => [
        'type' => 'plugin', // modules, plugins, field_types, extensions, themes...
    ],
]);

Declaring in form builders. Same syntax when adding fields at runtime in a settings module or admin controller:

$form->add('integration', 'anomaly.field_type.addon', [
    'label'  => 'Integration Handler',
    'config' => ['type' => 'module'],
]);

Reading the value. The stored value is the addon namespace string (vendor.slug), not an object. Two common patterns:

$namespace = $entry->integration->value;          // 'anomaly.module.dashboard'
$addon     = app('Anomaly\Streams\Platform\Addon\AddonManager')->get($namespace);
$label     = $addon?->name;                        // translated name

In Twig, the same:

{{ entry.integration.value }}          {# namespace #}
{{ entry.integration.presenter }}      {# translated label #}

Composing with addon_get(). For quick resolution in a service or view, addon_get($entry->integration->value) (or the addon() helper) avoids typing the manager out. Guard against null — a removed addon leaves a stale namespace on existing records.

Seeder / fixture pattern. Because the raw value is a string, seeders are trivial:

$entry->integration = 'vendor.module.some_integration';
$entry->save();

Pairing with a second field. A common shape is addon + a namespace-keyed config field (JSON, textarea) so admins select the addon then configure it. Key the second field's data by $entry->integration->value at read time.

Twig-side filtering. Since the field type only filters by addon class, not by install status, do secondary filtering in the presenter or a small view composer if you need "only enabled plugins."

Gotchas and Tips

  • type must match the collection method name. modules, plugins, field_types, extensions, themes — plural, snake_case. A wrong or singular value gives you an empty dropdown with no error, which is the most common "the package is broken" bug report. When in doubt, dump the collection in tinker: app('Anomaly\Streams\Platform\Addon\AddonCollection').

  • Values are namespaces, so be defensive on read. If an addon is uninstalled or renamed, $entry->integration->value still returns the old vendor.slug and addon_get() returns null. Wrap lookups ($addon?->name) and consider a migration that nulls orphaned references, or fall back to showing the raw namespace.

  • The translated label lives in the addon's own lang files. A dropdown entry showing addon::addon.name means the target addon is missing resources/lang/{locale}/addon.php, not that this field type is misconfigured.

  • Cache / registry staleness. The addon collection is built from the scanned manifest. If you create an addon and the field's dropdown doesn't show it, clear the framework cache and re-dump autoload (composer dump-autoload && php artisan cache:clear), then re-open the form — the options are enumerated per request but the scan itself is cached.

  • Do not use it for relationships. This is not a relation field. It stores a string. If you need to build a real relationship to content (entries, users), use the appropriate relation field type; a common anti-pattern is reaching for this to "point at another stream."

  • No dependency injection in options. getOptions() reads from the container-resolved collection synchronously. If your type depends on tenant/multi-site state, do the filtering in a custom subclass rather than trying to cram logic into config.

  • Extension point. The cleanest customization is to extend AddonFieldType and override getOptions() — for example, to exclude the addon currently being edited, or to restrict by vendor. Register the subclass as its own field type addon; override getOptions() rather than editing vendor code so composer updates don't clobber you.

  • Version pin quietly. Because the package is effectively core-adjacent but independently versioned, mismatches with anomaly/streams-platform can produce a "FieldType not found" boot error rather than a helpful message. Pin it alongside Streams in composer.json and upgrade them together.

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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console