anomaly/file-field_type
File field type for the Anomaly Streams platform. Adds a file upload field to Streams entries, letting you store, browse, and manage files through Laravel’s filesystem and the Streams control panel.
The file field type is a Streams Platform addon, so it only makes sense inside a Laravel app that already has anomaly/streams-platform (i.e. PyroCMS or a bare Streams install) plus anomaly/files-module for actual storage.
composer require anomaly/file-field_type
php artisan addon:install anomaly/file_field_type
php artisan migrate
Look at these first, in order:
src/FileFieldType.php — the addon class; it wires the accessor, mutator, input view, and validation.src/FileFieldTypeServiceProvider.php — routes, bindings, view namespaces.resources/views/input.tabular / input.php — the CP form partial (a file picker backed by the files module).config/ in the parent files-module — where the storage disk and folders live.First use case: add a file field to an existing stream (Users, Pages, a custom documents stream) and upload a PDF from the control panel. Once an entry has a file ID, $entry->document returns a File model, and $entry->document->url() / ->name() / ->size() behave like the files module.
// app/.../migrations or a seeder
$stream->addField('attachment', 'file', [
'allowed' => 'pdf,docx',
'max_size' => 10240,
]);
Control panel form. In the stream assignment, point a field at file and the CP renders the uploader. The submitted value is the file ID, so you get thumbnails/previews for free from the files module.
Twig/front-end access. The accessor hydrates the ID into a File model, so you can go straight to methods:
{% if entry.attachment %}
<a href="{{ entry.attachment.url() }}">{{ entry.attachment.name() }}</a>
{% endif %}
Programmatic writes. When seeding content or handling an API request, upload through the files module and assign the returned ID to the field:
$file = app(\Anomaly\FilesModule\File\Contract\FileRepositoryInterface::class)
->upload('documents', $request->file('attachment'));
$entry->attachment = $file->getId();
$entry->save();
Accessor/mutator contract. getAccessor() returns a closure that resolves the ID to a File; getMutator() accepts an int, an array of IDs, or an UploadedFile/File instance, making it safe for both CP and API paths. If you need custom behavior (e.g., storing multiple files), subclass FileFieldType and override the two closures rather than modifying vendor code.
Composing with images. For thumbnail-heavy content prefer anomaly/image-field_type; for anything else (PDFs, archives, downloads) keep the plain file type and render a link, since there is no image processing here.
Reusable custom modules. Depend on anomaly/file-field_type from your own addon's composer.json and reference the field slug file in your stream definitions — you never touch the class directly.
0.66 score mean this is essentially a single-author addon. Pin an exact tag in composer.json and be prepared to vendor-fork; don't assume Laravel-version compatibility beyond what the parent Streams branch ships.anomaly/files-module first, otherwise the field silently shows nothing or the accessor returns null because the repository binding is missing. composer require anomaly/files-module && php artisan addon:install anomaly/files_module.files rows with no references if storage cost matters.local/public), not its own. Changing config/files.php or the S3 credentials affects every file upload in the app at once.allowed and max_size in the assignment are the only guards the field type enforces; add mimes:/max: rules on your form requests if you accept writes from outside the CP.with('attachment') on your query or batch-resolve IDs via FileRepository.resources/{theme}/streams/file-field_type/ to customize the picker without forking the package.storage/logs/laravel.log, then php artisan streams:compile (clears the addon/field registry cache), and php artisan addon:list to confirm the field type is registered as file.How can I help you explore Laravel packages today?