panthro's avatar

Best practice for saving data and an image - if one of these savings fails?

I create a row of data in my database.

The image that goes with this data is uploaded on a model created event.

Now, if there's an issue with the image, the data still sits in the database.

Alternatively, if I upload the image first, then save the row in the database, if there's an issue with the data, we have uplaoded an image for no reason.

What would be the best set up for a situation like this?

Would it be prudent to change the even to an on creating event and abort if the image is not saved? Although, in this situation, what happens if on creating the image is saved, yet when the row is created it fails. Again, uploading an image for no reason.

What would be best practice?

0 likes
3 replies
kaplay's avatar

I have a solution for that maybe its can be best :)

public function store(Request $request) {

    $saved = null;
    $uploadedImage = null;
    $post = new Post($request->validated());
    
    try {
    
        if ($request->hasFile('file') {
            $uploadedImage = $request->file('file')->store('path');
            $post->image = $uploadedImage;
        }
        
        $saved = $post->save()
        
    } catch (\Exception $e) {
    
        if ($saved) {
            $saved->delete();
        }
        
        if ($uploadedImage) {
            Storage::delete($uploadedImage);
        }
        
    }
    
}
1 like
martinbean's avatar

@panthro One solution is to upload images to a “temporary” location, and then only copy the image to the actual disk if the corresponding record is saved. The temporary location is then cleaned up periodically (i.e. daily) so any images that were uploaded but not used or purged. This is what Laravel Vapor does, for example using an S3 lifecycle rule.

So when a user uploads an image, do it asynchronously and then in your controller, copy the image from the temporary location to your actual disk.

1 like

Please or to participate in this conversation.