Чтение
документации и изучение
хорошей пратики всё таки немного облегчает жизнь.
Итак.
Хранить в БД url, как делаете вы, обычно не выгодно и неинтересно. Это нужно в исключительных случаях одно разового мини проекта, когда вы точно знаете настроки меняться не будут и файлы редактироваться не будут. Либо, в специализированных БД для кеширования результата генерации url.
В иных случаях хранить в БД нужно имя файла. Имя файла в идеале разбить конечно, но в подавляющем числе случаев достаточно будет два поля: имя с путём + имя диска. Это закроет большинство кейсов для будущего масштабирования. Но если уж совсем лень, то имя диска тоже можно опустить, хотя я советую добавить это поле.
Далее, ваш код:
$path = Storage::putFile('public/img', $request->file('img'));
$url = Storage::url($path);
$post->img = $url;
Меняем на более простой (хотя аналог можно и из вашего конечно сделать, убрав строчку с $url и сохраняя в модель $path)
// file('img') - это имя файла(инпута формы например) из запроса
// store('img') - это имя подпапки для
// 'public' - Диск из настроек (см filesystems.php)
$path = $request->file('img')->store('img', 'public');
$post->img = $path;
Теперь и удалать легко. не забываем что с файлами мы работаем(по умолчанию), относительно папки
/storage/app/
(слеш в начале я поставил чтобы показать что путь от корня папки с проектом)
Поэтому, когда вы передаёте в метод удаления сгенерированный заранее url. он ничего не найдёт и не удалит.
Но теперь мы храним как раз относительный путь файла.
Storage::delete($post->img);
Теперь сработает, не забываем очистить поле, после удаления, если вы при этом не удаляете сам пост.
Далее, сам url получаем так
$url = asset($post->img);
Ну, или если вы делаете сразу в blade шаблонах
<img src="{{asset($post->img)}}">
Ну и конечно я всякие проверки и тп опустил для простоты