Using Laravel 7, I can upload, add and delete all images from a task (post if it were a blog) but I am unclear on how to delete a single image from a task view (single post view). I am using resource controller for tasks but I assume I will need a different function. I created one in the same TasksController and about the resource controller, I created a delete route for it. My application complains that I am trying to get a property ‘task_name’ of non object when I click the single image delete button. I am not sure how to go about this or if I need to create an Image Controller (of which I am not using at the moment). I will show what I am attempting and maybe, you can tell me if I am off base or share some recommendations. So, to start off with, here is my web.php:
<?php use IlluminateSupportFacadesAuth; use IlluminateSupportFacadesRoute; Route::get('/', function () { return view('welcome'); }); Auth::routes(); Route::get('/home', 'HomeController@index')->name('home'); Route::get('/users', 'UsersController@index'); Route::delete('delete-image', 'TasksController@delete')->name('delete-image'); Route::resource('tasks', 'TasksController'); Route::resource('users', 'UsersController');
My TasksController showing both my destroy method as well as my newly created delete method:
public function destroy($id) { $task = Task::with('images')->findOrFail($id); foreach ($task->images as $image) { Storage::disk('public')->delete('upload/' . $image->name); } $task->images()->delete(); $task->delete(); return redirect('home')->with('success', 'Task Deleted'); } public function delete($id) { // $task = Task::with('images')->findOrFail($id); $task->images()->delete(); $images = Image::find($id); Storage::disk('public')->delete('upload/' . $images->name); $images->name()->delete(); return redirect('home')->with('success', 'Task Deleted'); }
In my show.blade.php which would act as a single post view:
<div class="col-md-12"> <h5>Images</h5> <hr /> <div class="row"> @if($task->images->count()>0) @for($i=0; $i < count($images = $task->images()->get()); $i++) <div class="col-lg-4 col-md-6 col-sm-12"> <a href="delete-image" class="badge badge-danger p-2 mb-3">Delete</a><br> <a href="#" class="thumbnail" data-toggle="modal" data-target="#lightbox"><img class="w-50 mb-2" src="/storage/upload/{{ $images[$i]['name'] }}" alt=""></a> </div> @endfor @else <p>No images found</p> @endif </div> <br /> </div>
In my Image.php Model my relationships are as follows:
public function task() { return $this->belongsTo('AppTask', 'task_id'); // return $this->belongsTo(Task::class); } public static function boot() { parent::boot(); self::deleting(function ($images) { // File::delete(Storage::path($images['name'])); File::delete(str_replace('\', '/', storage_path('app/public/upload/' . $images->name))); }); }
and in my Task.php Model:
public function images() { // return $this->hasMany('AppImage'); return $this->hasMany(Image::class); } public static function boot() { parent::boot(); self::deleting(function ($task) { foreach ($task->image ?: [] as $image) { $image->delete(); } }); }
If I missed anything, please let me know so I can modify my question. I really appreciate the help on this as I am a week behind. Thank you in advance.
Advertisement
Answer
You need to pass the particular image_id to delete it. I have also made some changes for cleaner code:
<div class="row"> @forelse($task->images as $image) <div class="col-lg-4 col-md-6 col-sm-12"> <a href="delete-image/{{$image->id}}" class="badge badge-danger p-2 mb-3">Delete</a><br> <a href="#" class="thumbnail" data-toggle="modal" data-target="#lightbox"> <img class="w-50 mb-2" src="/storage/upload/{{ $image->name }}" alt=""></a> </div> @empty <p>No images found</p> @endforelse </div>
Note that delete button now takes you to …/delete-image/{image_id}
then on controller find the id and delete it.
Update your route file to accept id as Variable
Route::delete('delete-image/{image_id}', 'TasksController@delete')->name('delete-image');
then on controller variable can be accessed as
public function delete($image_id, Request $request) { # code... }