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

Files Laravel Package

laravel-enso/files

File management package for Laravel Enso that adds uploads, browsing, and organization of files and folders, polymorphic attachments, image processing, and ready-to-use Vue components for handling files in Enso applications.

View on GitHub
Deep Wiki
Context7

Getting Started

This package is an add-on inside the Laravel Enso ecosystem — it is not a standalone upload library and expects Enso core (laravel-enso/enso, which pulls in Structure, Forms, Actions, etc.) to be installed. If you are not already running Enso, treat this as a reference implementation rather than a dependency you can drop into a generic Laravel app.

Minimal steps:

composer require laravel-enso/files
php artisan migrate          # creates the polymorphic `files` table
php artisan storage:link     # files are resolved through Storage, not raw paths

Where to look first, in this order:

  1. config/files.php (or the enso.files block) — disk, size limits, mime filters, image options.
  2. src/Models/File.php — the schema shape (fileable_type, fileable_id, type, path, original_name, mime_type, size, is_public).
  3. src/Traits/Fileable.php — the trait you add to your own models.
  4. src/Services/* and any Actions/ folder — the upload and delete flows you should call instead of touching the model directly.

Your first useful case: attach an avatar or attachment to an Eloquent model.

use LaravelEnso\Files\Traits\Fileable;

class Post extends Model
{
    use Fileable;
}

$post->upload($request->file('image'), type: 'cover');
$post->file('cover'); // first file of that type

If the API surface differs in your pinned version, the trait is the single file to read to see the actual method names.

Implementation Patterns

Always upload through the package service, not $file->store(). The service is what wires original_name, mime_type, the type slot, and the storage disk consistently. Hand-rolled store() calls produce rows the rest of Enso cannot interpret.

Use type as a slot key. A model typically wants several distinct files — avatar, cover, attachment. Enso's file UI and file($type) helper assume this, so pick a stable naming convention and stick to it.

Upload from the backend UI via Enso actions. In an Enso form, the file input is a Vue component bound to a backend action that receives the fileable_type/fileable_id and returns the persisted file payload. Don't bypass it with a bespoke controller unless you also replicate the response shape the JS layer expects.

Validate with a FormRequest first, then upload. Enso's file uploader is convenient but the package will happily store a 40 MB video if your config allows it. Validate mime and size in the request, and mirror the same limits in config so the front end shows the right message.

Deletion must be explicit. Files are a polymorphic child table; deleting the parent model does not automatically clean up files rows unless your migration uses onDelete('cascade') and the driver enforces it, or you add an observer. The safe pattern:

class PostObserver
{
    public function deleted(Post $post): void
    {
        $post->files->each->delete(); // deletes row + storage object
    }
}

Use it for image-heavy resources sparingly. If you need thumbnails, resized variants, or CDN transformations, confirm whether your version of the package does image processing at all — in many Enso versions that lives in a separate image package or is left to you.

Config is the integration point. Disk selection, public vs private visibility, allowed mimes, and max size all flow from config into the service. Change config rather than overriding the service class.

Gotchas and Tips

  • Enso coupling is the biggest cost. Installing this drags in the Enso core dependency graph. If you only want "files attached to models," this is the wrong tool — a morphMany plus Flysystem is a tenth of the weight.
  • Low bus factor. 16 stars, tight version alignment with Enso, and Laravel major-version tracking that follows Enso's release cadence rather than Laravel's. Pin your version in composer.json and test on upgrades; don't assume ^ is safe.
  • Public/private visibility bites late. Files written to a private disk are not reachable via asset() or a plain URL. If you switch is_public or the disk after the fact, existing rows keep the old path and break — plan visibility up front.
  • Morph maps are respected only if you configure them. If you use Relation::enforceMorphMap(), the fileable_type column stores your alias, not the FQCN. Any manual query against files must use the alias.
  • Orphaned files accumulate silently. Failed validations, interrupted uploads, and removed UI elements all leave temp rows. Add a scheduled cleanup that deletes files rows whose created_at is old and whose fileable_id is null (or whose parent no longer exists), and pair it with storage pruning.
  • Don't mix Storage and direct filesystem paths. The package resolves through Storage::disk(config(...)). If you write directly with file_put_contents the row and the disk diverge, and ->delete() will no-op on storage without warning.
  • Debugging checklist when a file "disappears": (1) row in files table? (2) path matches what's on the disk? (3) storage:link still valid? (4) correct disk from config? (5) is_public matches the URL you're generating?
  • Extension points are narrow. You can swap the File model and tune config, but the service layer is opinionated. If your needs diverge (virus scanning, S3 multipart, signed URLs with TTLs), write a decorator around the service rather than editing the vendor package.
  • The type field is a string, not an enum. Nothing prevents avatar and avatars coexisting. Keep a constants class per model and use it in both backend and front end.
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.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package