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

Laravel File Cache Laravel Package

biigle/laravel-file-cache

A Laravel package for caching file contents and related data with automatic invalidation when the underlying file changes. It provides a simple file-aware cache layer to speed up repeated reads while keeping cached results fresh.

View on GitHub
Deep Wiki
Context7

Getting Started

The package solves one narrow problem well: given some source of a file (a path on a local disk, an object on an S3-style disk, or an HTTP(S) URL), give me a durable local copy plus a database record I can reference later. It is not a general asset pipeline, so the fastest way to evaluate it is to wire it to a single real use case — e.g. "download a user-supplied PDF/image from a URL once, then serve it from disk forever."

Minimal setup:

composer require biigle/laravel-file-cache
php artisan vendor:publish --provider="Biigle\FileCache\FileCacheServiceProvider"
php artisan migrate

Then inspect, in this order:

  1. config/file-cache.php — the disk the cache writes to, retention/max-age, and any route/middleware settings. This is the file you will actually change.
  2. The published migration / FileCache model — this tells you what is stored per file (source path or URL, local path, size, MIME type, timestamp). Everything else in your app should reference this record, not the raw URL.
  3. The Biigle\FileCache\FileCache service class — the entry point you inject or resolve.
  4. The service provider — to see whether it registers a route/controller for serving cached files and a cleanup command.

First use case, in a controller or job:

use Biigle\FileCache\FileCache;

$cache = app(FileCache::class);

// Remote URL, local path, or "disk:path" — same API, different source
$file = $cache->get('https://example.org/reports/q1.pdf');

// $file is the FileCache record; the package gives you the local path
// (and, if route serving is enabled, a URL) from it.
return response()->file($file->path);

If you only have ten minutes, verify two things: (a) calling get() twice on the same source does not re-download, and (b) php artisan migrate created the table and the file physically appears on the configured disk. If both hold, the rest of the package is detail. Note that exact method and attribute names (get(), path, url, etc.) have shifted across releases — check the README for your pinned version before copying snippets.

Implementation Patterns

Resolve once, store the ID. The single most valuable habit: after fetching, persist file_cache_id on your own model (or a polymorphic relation) instead of re-passing the URL everywhere. Your Report row then points at a cache record that can be re-served, re-pruned, and inspected independently of the origin. It also makes deletion deterministic — when the owning model is deleted, you know exactly which cache entry to release.

On-demand fetch in a request path, but only for small/slow-tolerant files. The fetch is synchronous. For thumbnails, avatars, or small documents this is fine and keeps the code tiny:

public function avatar(User $user)
{
    $file = app(FileCache::class)->get($user->avatar_url);

    return response()->file($file->path, ['Content-Type' => $file->mime_type]);
}

For anything user-facing and large, push it into a queued job and have the request path only ever hit already-cached entries (404 or placeholder if missing).

Warming and pre-fetching. A scheduled command that iterates your sources and calls get() is the natural companion to the synchronous read path. Combine it with the package's pruning/cleanup command in the same schedule so fetch and eviction stay in balance. This is the pattern the package is really built for: fetch out-of-band, serve cheaply in-band.

Serving through the package vs. serving yourself. If the service provider registers a file-serving route, use it when you need centralised auth middleware, signed URLs, or a stable public URL that outlives your storage layout. Serve yourself (response()->file(), StreamedResponse) when you need range requests, custom headers, or you are already behind your own authorization layer. Do not do both for the same disk — pick one and make it the only public path.

Force refresh and invalidation. Treat the cache as derived data. When the origin changes, or when you knowingly pushed a bad file, call the service in a way that bypasses/replaces the existing entry (force flag or delete-then-get). Wire an admin action or an event listener so operators are not editing the table by hand.

Testing integration. Storage::fake() the cache disk and Http::fake() the remote origin; then assert on both the database row and the fake disk contents. For expiry/retention behaviour, freeze time (travel() / Carbon::setTestNow()) rather than waiting on real timestamps.

Gotchas and Tips

  • Two stores, one logical file. Every entry is a DB row and a file on disk. Deleting one without the other leaks storage or leaves dangling references. Centralise cleanup in a model event or a single service method; never ->delete() the row ad hoc.
  • Pruning is opt-in. Retention/max-age config does nothing unless the cleanup command actually runs. Put it in app/Console/Kernel.php (or the scheduler) on day one, otherwise the disk grows silently until someone notices in production.
  • The cache disk must be a local filesystem if you intend to use response()->file() or hand paths to other PHP code. If you point the config at an S3 disk, you can still cache, but serving has to stream through the app (Storage::disk(...)->response(...)), which changes your performance profile entirely.
  • Concurrent misses race. Two requests for the same uncached source will both fetch. Wrap the fetch in Cache::lock("file-cache:{$sourceKey}") and re-check after acquiring; on a busy endpoint this is the difference between one download and fifty.
  • Remote origins lie. A slow or misconfigured webserver can return a 200 with an HTML error page. Validate Content-Type and size after the fetch before you trust the record, and set an explicit HTTP timeout on the underlying client — the default may be longer than your request timeout.
  • Signed URLs and proxies. If you use the package's serving route with signed URLs behind a load balancer, APP_URL and TrustProxies must be right or every signature fails intermittently. This is a classic "works locally, 403s in staging" bug.
  • Source identity is the cache key. Changing a URL by even a query string typically produces a brand-new entry. Normalise URLs (strip volatile params) before calling get() if you expect hits.
  • Lumen needs manual wiring. No package auto-discovery: register the service provider in bootstrap/app.php, copy the config file by hand (vendor:publish is unavailable), and either load the migration from the package path or copy it into database/migrations. Facades and route registration may also need explicit enabling.
  • Pinning matters. With a small maintenance surface and infrequent releases, the API is stable but not frozen — lock the version in composer.json and re-run your integration test on upgrade, particularly around expiry semantics and the served-file URL.
  • Extension points are thin but sufficient. The package is small; if you need custom naming, MIME sniffing, or per-tenant cache directories, bind your own subclass of the service (or a decorator around it) in a service provider rather than forking. Keep that binding as the single seam so the rest of your code never touches the package directly.
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.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo