Home > Enterprise >  Laravel 8 - Gracefully Handle Failed Delete Requests
Laravel 8 - Gracefully Handle Failed Delete Requests

Time:10-05

If a user wants to delete a record, say from the Country table, but it is parent to other records in the database and the foreign key is constrained (i.e. I do not want to cascade deletes), the delete fails and an unhandled error is thrown. Is there a way to avoid this and return a handled error using a Request? I have requests for storing and updating records, but I cannot find any examples for running validation against deleting a record.

According to the docs, there is a validation rule for Exists, but not for Not Exists. I tried this but it doesn't work:

public function rules()
{
    return [
        'id' => '!exists:states,country_id'
    ];
}

CodePudding user response:

You can use the unique validation. It will verify that no entries in the states table has a country_id of that value. it work even if it is not ment to be used like that.

Dont forget to change the error message or it would make no sense.

public function rules()
{
    return [
        'id' => 'unique:states,country_id'
    ];
}

CodePudding user response:

Check the relationship, if it isn't empty you can ask to user if he want really to delete this record, then if user accept, you can delete record and every where it is foreign key

CodePudding user response:

I ended up finding this tutorial on YouTube. He recommends using withCount to check if the delete is appropriate:

public function destroy(int $id) {
    $country = Country::withCount('states')->findOrFail($id);

    if ($country->states_count === 0) {
        $country->delete();
        return redirect()->route('countries.index')->with('message', 'Country Deleted Successfully');
    }
    return redirect()->route('countries.index')->with('message', 'Could not delete country ' . $country->name);
}

I am also doing this in the index() function in the Controller:

$countries =  Country::query()->withCount('states');

And then this in the View:

@if ($country->states_count === 0)
    <form method="POST" action="{{ route('countries.destroy', $country->id) }}">
        @csrf
        @method('DELETE')
        <button class="btn btn-danger">Delete</button>
    </form>
@endif
  • Related