Getting started
Laravel
Attach files to Eloquent models with one string column. The same policies, IDs and delivery as every other stack.
The API key is scoped to a project and can upload, sign and delete. Keep it on your server. Browsers upload through routes this package registers in your app — see Browser-direct uploads.
Install#
composer require filehutch/filehutch-php# .env
FILE_HUTCH_API_KEY=fh_… # Dashboard → API keysThe service provider and the FileHutch facade are discovered automatically.
PHP 8.2 and up, Laravel 11 and 12.
use FileHutch\Laravel\Facades\FileHutch;
FileHutch::upload($request->file('report'), policy: 'documents');Add the column and the attachment#
One string column per attachment. No blobs table, no attachments table, no disk configuration.
Schema::table('users', fn (Blueprint $table) => $table->string('avatar_file_id')->nullable());use FileHutch\Laravel\HasHutch;
class User extends Model
{
use HasHutch;
protected function hutches(): array
{
return ['avatar' => 'avatars'];
}
}Use it#
// Assign an uploaded file. Goes to storage on save.
$user->avatar = $request->file('avatar');
$user->save();
// Read it back
$user->avatar_url; // public policies
$user->avatarSignedUrl(expiresIn: 600); // any file
$user->avatarTransformUrl('thumb'); // a named transform
// Remove it, remotely and locally
$user->purgeAvatar();A wrong content type or an oversized file becomes a ValidationException on
save(), keyed by the attachment name, before anything leaves your server —
the policy is checked locally first.
Browser-direct uploads#
Bytes go from the browser straight to storage; only two small JSON calls touch
your app. The package registers them at /file_hutch/uploads, closed until you
say who may upload, in a service provider's boot:
use FileHutch\Laravel\DirectUploads;
use Illuminate\Http\Request;
DirectUploads::authorize(fn (Request $request, string $policy) =>
$request->user() !== null && $policy === 'avatars');The browser half is the <filehutch-upload> element from the TypeScript SDK.
It posts to /file_hutch/uploads by default and reads Laravel's CSRF token from
the csrf-token meta tag, so it needs nothing but a policy.
// resources/js/app.js
import { defineUploadElement } from "@filehutch/sdk/browser"
defineUploadElement()<filehutch-upload policy="avatars" name="avatar" accept="image/*"></filehutch-upload>On success the field holds the file ID, and assigning it is one line; the attachment checks on save that it is a ready file under its policy.
if ($request->filled('avatar')) {
$request->user()->update(['avatar' => $request->input('avatar')]);
}More in Browser uploads and the package README.