crodas/file-util
A small PHP utility library for everyday file operations, with helpers for reading, writing, and inspecting files and paths. Useful for simplifying common filesystem tasks in Laravel or plain PHP projects.
crodas/file-util is a framework-agnostic PHP file/path utility library, not a Laravel package — there is no service provider, facade, or config/file-util.php to publish. That shapes how you onboard it.
composer require crodas/file-util. It has zero dependents and is tiny, so it drops into any Laravel 8–11 app without conflicts.src/ tree on GitHub. You are looking for a small handful of classes, typically FileUtils\File, FileUtils\Dir, and a lockable/temp-file helper. Skim the constructors and public methods before using it — with 2 stars, the README is your only real spec.File::put() (Laravel's native helper) is not enough. Reports, exports, and config dumps that must not be half-written if the process dies:use FileUtils\File;
$report = new File(storage_path('app/reports/'.now()->format('Y-m-d').'.csv'));
$report->write($csv); // write via temp file + rename, so readers never see partial data
That single swap — Storage::put → FileUtils\File::write on a local disk — is the highest-value reason to add this dependency. If you only ever write to local disk and never worry about partial writes or locks, you do not need this package; Laravel's Storage facade already covers you.
Atomic replace for generated artifacts. Put the File writes behind a small service so you can test them and swap the implementation later:
namespace App\Support;
use FileUtils\File;
class AtomicWriter
{
public function put(string $absolutePath, string $contents): void
{
(new File($absolutePath))->write($contents);
}
}
Call it from export jobs, scheduled commands (app/Console/Commands/*), and queued listeners. This keeps FileUtils\File out of controllers and models.
Directory prep before writes. For per-tenant or per-day folder structures, use FileUtils\Dir (or its static helpers) to create recursive directories with correct permissions rather than chaining mkdir() calls:
use FileUtils\Dir;
$dir = new Dir(storage_path("app/tenants/{$tenant->id}/exports"));
$dir->create(0755, true); // recursive
Locking for concurrent writers. If two queue workers or two requests may touch the same file (append-only logs, counters), wrap the operation in the lockable file helper instead of flock() by hand. Keep lock scopes tight — acquire, write, release — and never hold a lock across an HTTP call.
Temp-file workflows. For anything that streams (ZIP exports, PDF merges), write into a FileUtils temp file, then move it into its final location. Combine with Laravel's response()->download() and have the job clean up in a finally block.
Boundary discipline. Use FileUtils only for the filesystem-touching layer. Everything above it (jobs, services, controllers) should call interfaces returning domain objects so tests can use a Storage::fake()-backed double, not these classes.
FileUtils\File/Dir yourself in a ServiceProvider if you want them injected.composer.json (e.g. "crodas/file-util": "^1.0") and add your own unit tests around any behavior you depend on — you will not get community bug reports to warn you.Storage::disk('s3')->put(...) for it; keep S3/GCS on Laravel's filesystem abstraction and use FileUtils for local scratch and atomic renames.Dir::create() are subject to the process umask, so 0755 can end up 0700-ish depending on the user the queue worker runs as. Assert the resulting permissions in a test, not just at call time.Illuminate\Contracts\Filesystem exceptions, so middleware and Handler::render won't recognize them. Catch the library's own exception classes at the service boundary and rethrow as RuntimeException/Illuminate\Filesystem\FilesystemException if you need consistent HTTP error responses.df -h) before suspecting the library. Also confirm storage_path() targets a directory the www-data/queue user can write to.App\Support\Filesystem adapter lets you migrate to league/flysystem or Laravel's Storage later without touching call sites — useful given the project's maintenance risk.How can I help you explore Laravel packages today?