F
Filament9mo ago
harps

Use record ID for file folder path

How would I use the record ID in the folder path to store files? I have tried the following
Forms\Components\FileUpload::make('shape_file')
->preserveFilenames()
// directory is record id of the project
->directory(fn ($record) => 'project-shapes/' . $record->id)
->previewable(false)
->downloadable()
->disk('private')
->visibility('public'),
Forms\Components\FileUpload::make('shape_file')
->preserveFilenames()
// directory is record id of the project
->directory(fn ($record) => 'project-shapes/' . $record->id)
->previewable(false)
->downloadable()
->disk('private')
->visibility('public'),
but get an error when creating new because the record does not exist yet. It does work if I create the record first then edit as the record already exists.
Solution:
I got this working with the following ``` protected function mutateFormDataBeforeCreate(array $data): array {...
Jump to solution
6 Replies
SirFat
SirFat9mo ago
The source of the ID would be controlled presumably by the database and not the application, that would be why. Is this just to cleanly separate files? Could you not let it save where it’s saving now and programmatically move it afterwards?
harps
harps9mo ago
Hi @SirFat , yeah it was just to make them clean and unique while maintaining the filename. I guess they could be moved with an eventListner but then would have to write that for a new and edit event.
SirFat
SirFat9mo ago
Yeah because of when the ID assignment occurs, if separation is that important - you don’t really have a choice 🙂
harps
harps9mo ago
I think another way would be to create a separate model for files and then in the form it creates the record first then the file. I've just found the docs about lifecycle hooks too.
Solution
harps
harps9mo ago
I got this working with the following
protected function mutateFormDataBeforeCreate(array $data): array
{
// Get the next auto increment from the datahase.
$nextAutoIncrement = ProjectResource::getModel()::max('id') + 1;
// Move the file from the temporary storage to the private storage.
Storage::disk('private')->move('project-shapes/' . $data['shape_file'], 'project-shapes/' . $nextAutoIncrement . '/' . $data['shape_file']);
// Change the file path to be the next auto increment.
$data['shape_file'] = 'project-shapes/' . $nextAutoIncrement . '/' . $data['shape_file'];

return $data;
}
protected function mutateFormDataBeforeCreate(array $data): array
{
// Get the next auto increment from the datahase.
$nextAutoIncrement = ProjectResource::getModel()::max('id') + 1;
// Move the file from the temporary storage to the private storage.
Storage::disk('private')->move('project-shapes/' . $data['shape_file'], 'project-shapes/' . $nextAutoIncrement . '/' . $data['shape_file']);
// Change the file path to be the next auto increment.
$data['shape_file'] = 'project-shapes/' . $nextAutoIncrement . '/' . $data['shape_file'];

return $data;
}
Only works on the form page not in a modal. Before the data is saved it gets the next available id from the model and then uses that. In the form I have this ->directory(fn ($record) => $record ? 'project-shapes/' . $record->id : 'project-shapes') So if you're in the edit screen it works as normal
SirFat
SirFat9mo ago
great work 🙂