Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Vladika-sys's avatar

Old avatar not deleted when uploading a new one

I am using Laravel Breeze to handle profile updates, and I have added functionality to allow users to update their avatar. Everything works fine, but the issue is that when a user uploads a new avatar, the old one isn't deleted from the filesystem.

I store avatars in storage/app/public/avatars/ and use php artisan storage:link to make them accessible. Here is my update method:

public function update(ProfileUpdateRequest $request): RedirectResponse
{
    $request->user()->fill($request->validated());

    if ($request->user()->isDirty('email')) {
        $request->user()->email_verified_at = null;
    }

    if ($request->hasFile('avatar')) {
        // Attempt to delete the old avatar
        Storage::disk('public')->delete('avatars/' . $request->user()->avatar);
        
        $file = $request->file('avatar');
        $fileName = Str::uuid() . '.' . $file->getClientOriginalExtension();
        $file->storeAs('avatars', $fileName, 'public');

        $request->user()->avatar = $fileName;
    }

    $request->user()->save();

    return Redirect::route('profile.edit');
}

However, after uploading a new avatar, the old avatar remains in the storage/app/public/avatars/ directory instead of being deleted.

What I’ve tried: Checked that Storage::disk('public')->delete('avatars/' . $request->user()->avatar); runs before the new file is stored. Verified that the file exists in storage/app/public/avatars/ before deleting. Debugged with dd(Storage::disk('public')->exists('avatars/' . $request->user()->avatar)); before the delete call. Confirmed that $request->hasFile('avatar') returns true, so the condition is being met. Removed everything from the function and tested only deletion:

dd(Storage::disk('public')->delete('avatars/' . $request->user()->avatar));

In this case, the avatar was successfully deleted, which makes this issue even stranger.

Questions: Why isn't the old avatar getting deleted in the full function? Could there be a reason why Storage::delete() works in isolation but not when used before storing a new file? How can I ensure that the old avatar is properly removed before saving the new one? Any insights would be greatly appreciated!

0 likes
7 replies
codedoktor's avatar

@vladika-sys Sounds very odd. One thing you could try out is to overwrite the file by simply storing the new avatar with the same name. You would also safe some lines of code and therefore improve performance by a little bit.

1 like
Vladika-sys's avatar
Vladika-sys
OP
Best Answer
Level 1

@codedoktor The problem was in the fact that after $reauest->user()->fill($request->validated()); $request->user()->avatar no longer contained the name of the old avatar, but the path to the newly added temporary file, like this [2025-02-10 12:35:41] local.INFO: Deleting avatar: C:\\Users\MyUser\AppData\Local\Temp\php88D2.tmp So, my current code looks like this

public function update(ProfileUpdateRequest $request): RedirectResponse
    {
        $oldAvatar = $request->user()->avatar;
        $request->user()->fill($request->validated());

   				 ...
        if ($request->hasFile('avatar')) {
            Storage::disk('public')->delete('avatars/' .$oldAvatar);
           
				...
        }

        $request->user()->save();

        return Redirect::route('profile.edit'));
    }
codedoktor's avatar

@Vladika-sys Ah, I see. I thought you might have checked that already... But congrats for finding the issue.

One more thing, I see that you are fetching the whole user object just to retrieve the avatar attribute. I would suggest you use:

User::select('avatar')->where('id', $request->user()->id)->first()->avatar;

if you only want to retrieve that specific column in order to slightly improve performance.

Vladika-sys's avatar

@codedoktor Honestly, that's what I did initially, but I thought it was pointless to query the database, when I already have what I need in $request->user(). But, thanks for the advice.

codedoktor's avatar

@Vladika-sys Yes you are right. If you have that already on the $request->user() object, you do not need an additional db query

1 like
martinbean's avatar

@Vladika-sys I’d only delete the “old” avatar after you’ve successfully uploaded the new one. Otherwise if there’s an issue saving the new one, the user will be left with no avatar if you’ve already deleted their existing one.

Please or to participate in this conversation.