givanov95/laravel-attachments
A Laravel package for adding file attachments to Eloquent models. It offers a simple, reusable API to associate, store, retrieve, and manage uploaded files, making it easy to attach documents or images to records without repeating upload logic across your application.
Architecture fit
Image, File), trait-based composition (HasImages, HasFiles), config-driven behavior, and package routes/controllers for destroy and order. Fits conventional Laravel application structure with no service container gymnastics or non-standard persistence.Attachment model plus an AttachmentLifecycle collaborator. This is a sensible direction: single source of truth for delete/restore/staging/physical-file removal reduces the classic "two copies drift apart" defect class.Integration feasibility
composer update plus an optional config publish. No API contract change for consuming frontends.attachments.extra_extensions config (default []) is additive and inert unless deliberately populated.Technical risk
svg, xml, json, and anything uncommon) are now persisted as .bin. This is a silent, per-file change with no error surfaced to the user..svg/.html/.xml files alongside .bin files, so the XSS exposure the release fixes is only closed for new uploads. Legacy files remain served with their original extension.Content-Type mapping — may regress on .bin.instanceof, concrete type-hints, Image::query() with custom scopes, per-model policies, observers, factories, or app-level subclasses of Image/File can break despite "public methods unchanged."Attachment. If soft deletes were not previously present on both models, default queries change (trashed rows excluded), which is a behavioral change the "no behaviour change" claim would not cover.extra_extensions is a foot-gun configuration knob. Once a team adds svg to restore an icon workflow, the vulnerability returns, and the config file is the only guardrail.Key questions
Image/File new or merely relocated? Any change to default query scope or withTrashed semantics?.bin affect only the stored filename/extension, or also the url accessor, download headers, and response Content-Type? Is X-Content-Type-Options: nosniff and Content-Disposition: attachment recommended or enforced?webp, avif, heic, mp4, webm, docx/xlsx, zip)?logo.svg vs logo.bin)?AttachmentController actions preserve per-model authorization, middleware, and route-model binding previously attached to the concrete controllers?Confidence caveat: this evaluation is derived solely from the v1.4.0 release notes; no source, test suite, or prior assessment was available.
Stack fit
Storage facade, public disk, Blade/Inertia/API frontends). No framework-version constraints are stated in the notes; verify composer.json against the app's Laravel and PHP versions before scheduling.url accessor and relations are unchanged, so SPA/API consumers should not need changes — provided they do not parse extensions client-side.Migration path
Image, File, Attachment, AttachmentLifecycle, and the merged controller rather than trusting the "no behaviour change" statement.config/attachments.php; leave extra_extensions empty as the default-deny baseline.extra_extensions entries only with a recorded justification and a note that reintroducing html/svg/xml/js reopens stored XSS..bin is served as an opaque download and legacy files cannot execute as markup.Compatibility
instanceof Image, instanceof File, type-hinted constructor/method parameters, custom subclasses of Image/File, morphMap entries, policies/observers/factories registered against the concrete classes, and any query using concrete-model scopes.Sequencing
.bin files download rather than render, and confirm legacy .svg/.html behavior is understood and accepted or remediated.extra_extensions additions as separate, reviewable changes..bin, so a future config edit cannot silently regress it.Maintenance
attachments.extra_extensions is a security-sensitive configuration. It needs an owner, a review gate, and a comment in the config explaining the XSS consequence. Treat edits like a permission change, not a preference.Support
.bin and the allowlist opt-in.Scaling
Content-Type metadata matters more than the extension; confirm how .bin objects are served and whether a CDN overrides content type. This is where a scaling-era misconfiguration could reintroduce XSS.AttachmentController and AttachmentLifecycle are neutral to scale; watch only for any query-shape changes from soft-delete scoping on large attachment tables.Failure modes
.bin files that no longer render, thumbnail, or parse — highest likelihood, lowest severity, highest ticket volume..html/.svg files; the fix is forward-looking only.svg to fix an icon workflow and reopens stored XSS on the app's own domain.Image/File.destroy/order.Ramp-up
How can I help you explore Laravel packages today?