@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.
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!
@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'));
}
Please or to participate in this conversation.