acacha/filesystem
acacha/filesystem is a Laravel package offering convenient filesystem helpers and abstractions for managing files, directories, and storage disks. It simplifies common file operations and integrates with Laravel's filesystem layer for cleaner PHP applications.
Install it like any other Composer library:
composer require acacha/filesystem
Before writing any application code, spend ten minutes in the repository itself:
composer.json — confirm the PSR-4 namespace (Acacha\Filesystem\...) and the minimum PHP version. At 24 stars and a score of 0.36, you are adopting a small, lightly-maintained package, so pin the version in composer.json rather than floating on dev-master.src/ — the two pieces you care about are the Filesystem class (likely extending or wrapping Illuminate\Filesystem\Filesystem or Symfony's Filesystem) and the stub compiler (typically StubCompiler, Stub, or a Compiler directory). Read the constructor signatures; that tells you what must be injected (base path, replacement map, etc.).tests/ or the README examples — with a package this size, the tests are the de-facto API documentation.Your first real use case is almost certainly scaffolding: you have a .stub file with placeholder tokens (e.g. DummyClass, DummyNamespace, {{ name }}) and you want to write out a fully-resolved file to disk. A minimal first flow:
use Acacha\Filesystem\Filesystem;
$fs = new Filesystem(__DIR__ . '/stubs'); // adjust: base path argument
$fs->copyCompiled('Controller.stub', app_path('Http/Controllers/FooController.php'), [
'DummyClass' => 'FooController',
'DummyNamespace' => 'App\Http\Controllers',
]);
If the exact method names differ, the pattern is always the same: read stub → apply replacement map → write to destination. Once that round-trip works on one file, you've validated the package for your use case.
1. Stub compiler for generators (the core value). This package exists so you don't hand-roll str_replace over template strings. Wrap it in an Artisan command or a plain PHP service:
class MakeWidgetCommand extends Command
{
protected $signature = 'make:widget {name}';
public function handle(Filesystem $fs): int
{
$name = Str::studly($this->argument('name'));
$fs->copyCompiled(
'widget.stub',
base_path("app/Widgets/{$name}.php"),
['DummyClass' => $name, 'DummyNamespace' => 'App\\Widgets']
);
return self::SUCCESS;
}
}
Bind the package's filesystem in a service provider so the base path and replacement defaults are configured once.
2. Composable replacement maps. Build the token map in a method that returns an array rather than inlining it. This lets you layer defaults (namespace, author, date) with per-command overrides:
$map = array_merge($this->defaultReplacements(), ['DummyClass' => $name]);
3. Pair with plain filesystem calls. The stub compiler handles one file; use the same Filesystem instance for makeDirectory, copyDirectory, deleteDirectory when a generator needs to emit a whole tree (e.g. a module with controllers, routes, and tests). Keeping both operations on one instance avoids path-resolution mismatches.
4. Idempotent generators. Guard the write with exists()/overwrite so re-running make:widget doesn't silently clobber user edits. Most packages expose an overwrite flag on the copy method — check the signature and default.
5. Test fixtures. Because the compiler is deterministic, use it in your test suite to generate fixture files (configs, migrations) rather than committing dozens of static copies. Snapshot the compiled output in a unit test to lock in the stub format.
6. Laravel integration. If you're on Laravel, register the package's service provider (auto-discovery may or may not be configured for a package this small — check composer.json extra.laravel.providers). Inject the filesystem via the container in commands and jobs rather than new Filesystem().
DummyClass), others Laravel's {{ }}. Read the stub file shipped with the package before authoring your own; a mismatched token fails silently and writes a file that still says DummyClass.read fails, log getcwd() and the resolved path — it is nearly always a ../../ mistake.copyCompiled/copy refuses to overwrite by default. In a scaffolding context you usually want refusal; in a migration context you don't. Make it explicit at the call site.www-data may not be able to write the target directory even though it can read the stub./, joining with DIRECTORY_SEPARATOR elsewhere can produce mixed separators. Prefer the package's own join/normalize helpers over raw string concatenation.StubGenerator) so you can swap it for a hand-rolled strtr implementation in an afternoon if it goes stale. Keep the composer constraint pinned.How can I help you explore Laravel packages today?