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

Documents Laravel Package

laravel-enso/documents

Laravel Enso Documents provides document management for Enso applications, letting you upload, store, organize, and attach files to models, with template support, permissions, and ready-made UI integration.

View on GitHub
Deep Wiki
Context7

Getting Started

laravel-enso/documents is a module in the Laravel Enso ecosystem, so it assumes Enso's core scaffolding (laravel-enso/enso, laravel-enso/helpers, laravel-enso/forms, laravel-enso/tables) is already in place. It is not a standalone upload package — its UI, permissions and routes are wired through Enso's Vue/Vuetify admin shell. If you don't have an Enso app, this package will fight you; use spatie/laravel-medialibrary instead.

Assuming an Enso app:

  1. composer require laravel-enso/documents
  2. Publish the migration/config (Enso packages usually expose documents config for storage disk and allowed types): php artisan vendor:publish --tag=documents then php artisan migrate
  3. Add the trait to any model that should own files:
    use LaravelEnso\Documents\Traits\HasDocuments;
    class User extends Model { use HasDocuments; }
    
  4. First use case — attaching a document to a user from a controller:
    $user->documents()->create(
        Document::attributesFrom($request->file('document'))
    );
    
    Or route the file through the package's own upload endpoint so it handles validation, disk naming and metadata in one place.

The first place to look in the repo is src/Models/Document.php (the shape of the record: name, original_name, mime, size, type, documentable_type/id), then src/Traits/HasDocuments.php, then the Vue components under resources/js if you're customising the front end.

Implementation Patterns

Polymorphic attachment. The documentable morph means one documents table serves every entity in your app. $company->documents, $user->documents, $invoice->documents all work without extra tables. Reach for the trait rather than hand-rolling join tables.

Typed documents. Enso uses a DocumentType enum on the record so uploads can be grouped (e.g. contract vs. identity vs. attachment). Pass the type on creation so listing/filtering in the front end works — the built-in list component filters by it.

FormBuilder integration. The package's Vue uploader slots directly into Enso's FormBuilder:

->file('document', 'contract')

This is the idiomatic day-to-day path — you rarely touch the upload controller yourself.

Download through a policy, not a raw URL. Documents live on the private disk. Serve downloads via the package's download endpoint (or your own StreamedResponse) so Enso's ACL runs. Never expose storage/app/documents as a public URL — that bypasses authorisation.

Cleanup on deletion. When a parent model is deleted, cascade its documents. Either add ->onDelete('cascade') to the morph column in your migration or hook a model observer to $model->documents()->each(fn($d) => $d->delete()) so the physical file is removed alongside the row.

Custom subtypes. Extend Document and override protected $fillable / add a scopeForType when you need domain logic (e.g. "latest signed contract"). Keep the base package untouched — Enso expects the parent class to remain canonical.

Event-driven post-processing. Listen for the package's DocumentCreated / DocumentDeleted events to hook OCR, virus scan, thumbnail generation, or Elastic sync without touching the upload flow.

Gotchas and Tips

  • Disk configuration. Default goes to the local/private disk under storage/app/documents. If you're on S3 in production, set the disk in config/documents.php and make sure the Enso policy lets the download controller generate a signed URL for the right disk — mismatches produce silent 404s.
  • PHP upload limits, not Laravel validation, bite first. upload_max_filesize and post_max_size in php.ini (and Nginx client_max_body_size) will kill large uploads before Validator runs. Symptom is a 413 or an empty $_FILES, not a validation error.
  • MIME allow-list lives in config. Adding a new type (e.g. .heic) requires updating config/documents.php and the front-end accept attribute if you use the Vue uploader.
  • Enso ACL is separate from Laravel policies. If the upload button doesn't appear for a role, check Enso's roles / permissions tables, not just Gate definitions. Missing a documents.* permission silently hides the UI.
  • File name collisions. The package generates storage names, but the original_name is what users see in the list. If you build your own listing, always surface original_name, and be aware two users can upload files with identical original names.
  • Tests need Storage::fake(). The package writes real files via the configured disk; without faking storage, test runs litter storage/app. Faking also catches disk-config mistakes early.
  • Version coupling is real. Enso v3 uses documentable_type strings, Enso v4 moved to enums and Vue 3. Mixing package versions with an older Enso core will break routes and Vue components — pin in composer.json and test upgrades.
  • Orphaned files after failed transactions. If a DB transaction rolls back after the file was written, the row disappears but the file stays. Wrap uploads in a try/catch that deletes the file on exception, or schedule a periodic orphan sweep comparing storage/app/documents against the documents table.
  • Debugging tips. Enable Laravel file logging and look at the Enso request log (storage/logs/enso.log if present). If the Vue uploader appears but silently fails, check the browser network tab for the /api/documents response — Enso returns 422 with a message key rather than throwing.
  • Extension points. Document::observe(...) and the package events are the safest hooks. Avoid overriding Document::create() unless you truly need to — you'll fight future upgrades.
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.
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
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle