Reputation: 565
I am trying to delete a file through routes.php but it is generating the following error:
FatalErrorException in routes.php line 113: Call to a member function delete() on null
This is the view where the function is placed in the delete button.
<div class="col-md-12 col-xs-12">
<div class="row">
@foreach($properties->files as $index=>$file)
<div class="col-sm-6 col-md-2">
<div class="thumbnail">
<img src="{{ URL::asset('uploads/products/' . $file->name) }}" alt="{{ $file->property_id }}" width="300" height="200">
<div class="caption">
<div class="caption" align="center">
<form action="{{ url('file/'.$file->id) }}" method="POST" enctype="multipart/form-data">
{{ csrf_field() }}
{{ method_field('DELETE') }}
<button onclick="return confirm('Está seguro eliminar esta imagen?')" class="button btn btn-danger btn-xs" data-toggle="tooltip" data-placement="top" title="Eliminar imagen"><i class="material-icons delete-white">delete</i></button>
</form>
</div>
</div>
</div>
</div>
@endforeach
</div>
</div>
And this is the path I'm using to delete the file in the directory and database.
// Delete files
Route::delete('/file/{id}', function ($id) {
//File::findOrFail($id)->delete();
$file = File::find(Input::get('id')->delete());
$filename= Input::get('upload');
$path = 'uploads/products/' . $file->filename;
//return redirect('/');
return redirect()->back()->with('success', 'Imagen eliminada satisfactoriamente!!!');
});
Upvotes: 0
Views: 227
Reputation: 565
Thanks for the recommendations, but I decided to change the method to handle these events.
1 - I create a new controller (FilesController) and through the controller I passed the parameters for elimination in the BD and the public path, for this controller we use the destroy method.
2 - I create a Route resource from the same controller.
This is the File model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class File extends Model
{
protected $table = 'files';
protected $fillable = ['name', 'property_id'];
// Relation with Property
public function property()
{
return $this->belongsTo('App\Property');
}
}
This is the FilesController method:
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\Input;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\File;
use Redirect;
use Storage;
class FilesController extends Controller
{
public function destroy(Request $request, $id)
{
$file = File::find($id);
$fileName = $file->name;
//dd($fileName);
$file_path = public_path() . "/uploads/products/" . $fileName;
//dd($file_path);
if(File::exists($file_path))
{
unlink($file_path);
}
$file->delete();
return redirect()->back()->with('success', 'Imagen eliminada satisfactoriamente!!!');
}
}
The route:
Route::resource('properties','PropertyController');
And this is the part in the view that delete the files:
<div class="col-md-12 col-xs-12">
<div class="row">
@foreach($properties->files as $index=>$file)
<div class="col-sm-4 col-md-2">
<div class="thumbnail">
<img src="{{ URL::asset('uploads/products/' . $file->name) }}" alt="{{ $file->property_id }}" width="300" height="200">
<div class="caption">
<div class="caption" align="center">
{!! Form::open(['method' => 'DELETE','route' => ['files.destroy', $file->id],'style'=>'display:inline']) !!}
{!! Form::hidden('_method', 'DELETE') !!}
{!! csrf_field() !!}
@permission('role-delete')
<button onclick="return confirm('Se eliminara la propiedad de la lista')" class="button btn btn-danger btn-xs" data-toggle="tooltip" data-placement="top" title="Eliminar imagen" data-id="{{$file->id}}"><i class="material-icons delete-white">delete</i></button>
@endpermission
{!! Form::close() !!}
</div>
</div>
</div>
</div>
@endforeach
</div>
</div>
With this simple form we can remove an image of the DB and the public path.
I hope to collaborate with other passionate people.
Upvotes: 1
Reputation: 178
The error is generated because you are trying to retrieve a value from an input field which does not exist. You should read the documentation and see the difference between Input and Request Requests & Input
Since there is no input field in your form and you are just passing and id in your form request, change this
$file = File::find(Input::get('id'))->delete();
to this
$file = File::find(Request::segment(2))->delete();
It should work fine now.
Updated:
Make sure you have your model class in your web route. Also make sure you're using Request use Illuminate\Http\Request;
In your web route use Request. Do the following:
Change this
// Delete files
Route::delete('/file/{id}', function ($id) {
//File::findOrFail($id)->delete();
$file = File::find(Input::get('id')->delete());
$filename= Input::get('upload');
$path = 'uploads/products/' . $file->filename;
//return redirect('/');
return redirect()->back()->with('success', 'Imagen eliminada satisfactoriamente!!!');
});
to this
// Delete files
Route::delete('/file/{id}', use function (Request $request) {
File::findOrFail($request->segment(2))->delete();
$filename= Input::get('upload');
$path = 'uploads/products/' . $file->filename;
//return redirect('/');
return redirect()->back()->with('success', 'Imagen eliminada satisfactoriamente!!!');
});
Upvotes: 1
Reputation: 62368
When processing request input, there are two types of parameters: route parameters and query parameters. Route parameters are part of the url and are made available as parameters to the route handler (closure or controller method), whereas query parameters come from the query string and are made available through the request data (Input facade that you are using).
As written, your code has two issues. First, your file id is a route parameter, but you're trying to access it as if it were a query parameter. Second, you're actually attempting to call delete()
on the id itself, which is actually null
since it doesn't exist as a query parameter.
The line that you have commented out should work fine:
File::findOrFail($id)->delete();
It looks like you're also attempting to delete a file from the file system when you delete your File
record. I would suggest you add a deleted()
event to your File
method, so that whenever a File
model is deleted, it deletes the associated file from the file system.
class File extends Model
{
public static function boot()
{
// make sure to call the parent boot
parent::boot();
// this function will be called whenever a File is deleted
static::deleted(function ($model) {
// delete the file when the model is deleted. very basic,
// you'll want to add in more sanity checks, etc.
// get the file path
$path = 'uploads/products/' . $model->filename;
// delete the file
unlink($path);
});
}
}
You could also use the deleting()
event, which will fire before the File record is deleted from the database. If you did this, you could return false
from the event if the file fails to delete, and that will prevent the record from being deleted from the database.
Upvotes: 1