The Upload model
The table
| Column | Meaning |
|---|---|
uploadable_type, uploadable_id | The model the upload belongs to; both null for an upload without owner |
user_id | The user who uploaded it, from auth()->id() at the time |
collection | The group the file is in: photos, files, attachments, any name you choose |
disk | The disk the file is on, copied from the config when it was stored |
path | The path on that disk: <prefix>/<models>/<id>/<collection>/<uuid>.<ext> |
name | The original file name, used for downloads |
mime_type, size | As detected when the file was stored; size in bytes |
is_public | Which disk it went to and what kind of URL it gets |
sort_order | Display order within its collection, from 0 |
meta | JSON with whatever you keep with the upload |
conversions | JSON with the paths of the generated files: the conversion names, and pages for a PDF |
processed_at | When the processing job ran; null until then |
deleted_at | Set by a soft delete |
The pair disk and path is unique.
Relations and scopes
$upload->uploadable; // the owning model, or null
$upload->user; // the uploader, resolved through the user model of the default auth provider
Upload::public(); // or ->private()
Upload::collection('photos');
Upload::ordered(); // sort_order, then id
Upload::images(); // mime type image/*
Upload::processed(); // the job has run
Upload::withTrashed(); // the usual soft delete scopes
URLs
| Method | Returns |
|---|---|
url() | The original: the disk URL for a public upload, a signed link for a private one |
downloadUrl() | The same, but a private link forces a download with the original name |
conversionUrl('thumb') | The conversion, or the original while it does not exist yet |
thumbnailUrl() | conversionUrl('thumb') |
pageUrl(2) | A rendered PDF page, or null when that page was not rendered |
Every method takes an optional $minutes that overrides link_expires_after_minutes for a signed link. Public uploads ignore it.
Type and state
$upload->isImage(); // image/*
$upload->isVideo(); // video/*
$upload->isPdf(); // application/pdf
$upload->isProcessed(); // processed_at is set
$upload->hasConversion('thumb');
$upload->conversionPath('thumb'); // path on the disk, or null
$upload->pagePaths(); // paths of the PDF pages
$upload->pageCount();
$upload->humanSize(); // "1.2 MB"
Meta data
meta is a JSON column for everything a project wants to keep with a file: a caption, print settings, the source of a generated image, an approval flag. Read and write it through dot keys:
$upload = $product->addUpload($file, 'photos', meta: ['caption' => 'Front', 'source' => 'phone']);
$upload->meta('caption'); // Front
$upload->meta('print.layer_height', 0.2); // default when the key is missing
$upload->setMeta('approved', true); // writes and saves
Add a real column in your own migration only when you have to filter or sort on the value; everything else belongs in meta.
The HasUploads trait
$product->uploads(); // MorphMany, ordered, without the trash
$product->uploadsIn('photos'); // one collection
$product->firstUpload('photos'); // the cover photo, or null
$product->addUpload($file, 'photos', public: true, meta: []);
$product->reorderUploads('photos', [12, 7, 9]); // ids not in the list keep their place after these
Darvis\Uploads\Contracts\UploadOwner declares the same methods. Implement it on the model when you want to type hint “a model with uploads”; the trait satisfies it and the Livewire upload manager is annotated with it.
The StoreUpload action
addUpload() calls Darvis\Uploads\Actions\StoreUpload. Use the action directly for an upload without an owner, or to set the uploader yourself in a job where nobody is logged in:
use Darvis\Uploads\Actions\StoreUpload;
$upload = app(StoreUpload::class)->handle(
$file,
collection: 'attachments',
public: false,
meta: ['from' => 'contact form'],
owner: null,
userId: $customer->id,
);
The action chooses the disk from is_public, builds the directory (uploads/<collection> without an owner), stores the file with storeAs(), which streams it so a Livewire temporary file on S3 is copied bucket to bucket, writes the row and dispatches Darvis\Uploads\Jobs\ProcessUpload.
Events
Darvis\Uploads\Events\UploadProcessed is dispatched when the job has written the conversions and pages, also for a file that gets none (processed_at is set anyway). Listen to it to react once a thumbnail exists, for example to send the photo to an image model or to notify someone.