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

Zipper Laravel Package

aerni/zipper

Aerni/Zipper is a Laravel package for creating, extracting, and managing ZIP archives through a simple, expressive API. It wraps PHP’s ZipArchive to handle files and folders with minimal configuration.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit

  • aerni/zipper is a single-purpose Statamic addon (Laravel package) that serves a ZIP of Statamic assets on request. It sits at the edge of the stack: a route/controller (or Antlers tag) that resolves asset IDs or paths, opens the underlying files from their container (local disk or S3-compatible), and returns an archive to the browser.
  • Fit is good only if we already run Statamic and have a concrete "download these N assets" workflow (product datasheets, media kits, photo galleries, client document bundles). It is not a general Laravel archiving utility and offers little to a non-Statamic application.
  • v2.5.1 confirms the architecture includes a persisted archive cache, not just a pass-through stream. That is a meaningful change to the fit picture: the package now owns state (files on disk plus cache entries) and requires a cache directory, a cleanup policy, and an invalidation story. Coupling moves from "presentation-adjacent and stateless" to "presentation-adjacent with a write path on our infrastructure." Blast radius is still bounded, but it is no longer zero.

Integration feasibility

  • Adoption cost remains low: composer require aerni/zipper, Statamic package auto-discovery registers the service provider, publish config, wire a template tag or hit the route. Hours, not days, for a working spike.
  • The unknown is still the security posture of the exposed endpoint. Any route that assembles assets by user-supplied IDs must be verified for: authorization against container/folder permissions, signed or expiring URLs, whether private containers are respected, and whether arbitrary path traversal or unlisted-asset enumeration is possible.
  • New in this review: the cache path must be reviewed with the same rigor as the route. Specifically, whether the cache key incorporates the requesting user's identity/permission set. If a cached archive is keyed only on asset IDs, two users with different entitlements could be served the same archive — a private-asset disclosure that survives the authorization check on the request path.
  • Verify the archive mechanism end to end: whether a cache miss streams (ZipStream-style, constant memory) or writes a temp file first (disk exhaustion and cleanup risk), and what the cache-on-disk footprint is at our expected size. Verify S3 behavior — every byte is proxied through PHP on a miss, which is correct for private assets but adds latency and egress; a hit avoids that, which is presumably the point of the cache.

Technical risk

  • Vendor risk is the dominant risk, not code risk. Small maintainer base and no significant dependent count. Effectively an unpinned, thinly-proven dependency — though see the mitigating signal below.
  • Mitigating signal (new): a 2.5.x version line plus an external contributor (PR #20) indicates a real release cadence and some outside participation, which is stronger evidence of maintenance than the prior snapshot suggested. Downgrade this from "unproven" to "thinly maintained but active."
  • Cache-path risk (new). The fix targets downloading a cached zip, i.e. a defect on the cache read path that shipped to users. Any code path that recently carried a correctness bug is a path that was less exercised than the primary one — treat cache hit, cache miss, cache invalidation, and cache expiry as four distinct test cases during the spike, and assume stale archives are possible until proven otherwise.
  • Version/metadata risk. Confirm Composer constraints (statamic/cms, laravel/framework, PHP) against our target majors. The existence of a 2.5.x line makes the earlier "single initial release" concern moot, but the constraint matrix still needs verification.
  • Mitigating factor: functional surface is still small. Forking or reimplementing in-house remains cheap (1–2 days for the streaming case; add ~1 day if we want the cache). Vendor risk is bounded, not unbounded.

Key questions

  1. Does the endpoint enforce Statamic asset-container permissions and asset-level access, or is it open by default?
  2. Is the archive cache key scoped to the user/permission set, or only to the asset set? What is the TTL, and what invalidates an entry when an asset is updated, moved, or made private? (New — highest-priority question after v2.5.1.)
  3. Where does the cache live, is it inside the web root, and what cleans it up? Is there a documented purge/cache:clear path?
  4. Does the fix in #20 address a stale-content bug, a permission bug, or a plain download error? The answer materially changes the risk rating.
  5. Streaming or temp-file on a cache miss? Memory and disk ceilings at our p95 archive size?
  6. Supported matrix: Statamic 4/5, Laravel 10/11/12, PHP 8.1–8.4?
  7. Does it handle nested folders, duplicate filenames across containers, and non-local (S3) drivers?
  8. Test coverage and issue responsiveness — does CI cover the cache path?

Integration Approach

Stack fit

  • Fits cleanly into a Statamic + Laravel stack that already uses asset containers as the source of truth. No competing abstraction: assets stay in containers, the addon only changes the transport format from "N downloads" to "one archive."
  • The cache introduces a second storage location to operate. Map it onto existing infrastructure (writable volume with a size quota, or the app's cache/storage/app tree) rather than letting the package own an unmanaged path.
  • Poor fit if assets live behind a separate DAM/CDN with pre-signed URL generation — the addon would bypass that control plane, and a cache would then hold copies of assets the DAM considers access-controlled.

Migration path

  • No data migration, but there is now a directory and lifecycle to provision. Treat it as an additive, reversible capability: introduce behind a feature flag, keep existing per-asset download links live, measure usage before removing anything.
  • Rollout order: (1) dev spike with a representative asset set, including at least one private container and one S3 container, (2) security review of the route and the cache key/permissions interaction, (3) load test at p95 archive size with a cold and a warm cache, (4) provision disk quota, TTL, and purge job, (5) production behind the flag, (6) remove the flag.

Compatibility

  • Pin an exact version in composer.json (now 2.5.1) and let Composer's platform requirements fail the build on a Laravel/Statamic upgrade. Do not float the constraint — a ^2.5 would pull a future cache-behavior change silently.
  • Verify S3/remote-driver parity in staging across both cache miss and cache hit; local disk is the happy path and will hide latency, permission, and staleness bugs.
  • If constraints do not cover our target Statamic major, prefer a thin in-house controller over a fork of a stale release — the cache feature is simple enough to replicate deliberately if needed.

Sequencing

  • Week 1: spike (cold + warm cache, private container, S3) + security review + compatibility verification.
  • Week 2: load test both cache states, decide build-vs-buy (fork vs. ~150–250-line in-house controller), define cache TTL/invalidation and disk quota, add endpoint-level rate limiting.
  • Week 3: flagship rollout behind the flag with telemetry on archive count, size, cache hit rate, and error rate.

Operational Impact

Maintenance

  • Code-churn surface is low and the project shows signs of life (2.5.x line, outside contributor), but it is still a small-maintainer project with no guaranteed fixes. Budget for owning a fork or a replacement path within one major-version cycle. Keep usage behind a thin internal service class (not calling the package directly from templates) so swapping it, or wrapping the cache in our own logic, is a one-file change.
  • New maintenance line item: monitor and prune the archive cache directory. A cache with no eviction policy is an unbounded disk leak.
  • MIT license removes legal friction; vendoring or forking is permissible.

Support

  • GitHub issues only — no SLA, no escalation path. Our own on-call owns failures. Acceptable for a non-critical convenience feature; unacceptable for a contractual deliverable (e.g., a customer-facing compliance export).
  • Because a patch release just fixed a cache-download bug, expect further cache-path defects. Do not put this behind a customer commitment until the cache has run clean in production for a full release cycle.

Scaling

  • ZIP assembly is CPU- and I/O-bound and occupies a PHP worker for the duration of the response. Throughput scales with worker pool size, not queue depth — the classic way a "download all" button degrades an otherwise healthy PHP-FPM pool.
  • The cache materially improves this on a hit (disk read, no per-asset fetch, no S3 egress) and is the feature most likely to make this viable at scale — provided concurrency is safe. Verify that simultaneous requests for the same uncached archive do not both assemble it, or a burst will multiply the expensive work instead of deduplicating it.
  • S3-backed assets amplify cost on a miss: N sequential fetches through PHP, N egress charges, duration bounded by the slowest object. Cap asset count/size per archive; move large bundles to an async job producing a signed, expiring link.
  • Cache storage grows with distinct asset sets, not with traffic — plan the quota against the number of distinct bundles, not request volume.

Failure modes

  • Stale archive served from cache after an asset was updated, replaced, or made private — silent, and the most likely failure given a fix just landed on the cache read path.
  • max_execution_time or proxy/gateway timeout → truncated ZIP that still looks like a valid download to the user (worst class, because it is silent).
  • Memory exhaustion if the implementation buffers rather than streams on a cache miss.
  • Disk exhaustion from temp files or an unbounded cache that is never cleaned.
  • Unauthorized access or asset enumeration if the route lacks permission checks, or if the cache key is not permission-scoped and one user's archive is served to another.
  • CDN or reverse-proxy caching of an authenticated archive, leaking private assets to other users.
  • Each needs an explicit guard: archive size caps, Content-Length/integrity checks, Cache-Control: private, no-store at the edge, auth middleware, cache TTL plus invalidation, disk quota with alerting, and alerting on 5xx rate, cache hit rate, and average response duration.

Ramp-up

  • Hours for any Laravel developer: the only domain knowledge required is Statamic asset containers and the asset fieldtype. No new language, no new deployment unit — but there is now a new operational responsibility (cache directory + purge), which should be documented as part of the runbook rather than learned during an incident.
  • The real onboarding cost remains the security review checklist for a file-serving endpoint, now extended with a cache-key/cache-invalidation section. Worth writing once and reusing for any future file-serving feature.
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.
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
adachsoft/php-code-style