Framework: Delete Utilizing Route Model Binding

Created on 8 Dec 2018  路  3Comments  路  Source: laravel/framework

  • Laravel Version: 5.7.#
  • PHP Version: 7
  • Database Driver & Version: MySQL 5

Description:

I have two models; pattern->hasMany('materials') & and material->belongsTo('pattern'). The CRUD functionality for the pattern model is working find and I'm focusing in the delete verb. The code below for the Pattern model works fine.

public function destroy(Pattern $pattern)
{
    $pattern->delete();
    return redirect(route('patterns.index'))
        ->with('success', 'Pattern was deleted successfully.');
}

As one can notice I'm using the model binding capabilities and the method destroy does work.

The child model (materials) has the same functionality. If I use the Model binding the destroy method doesn't work

public function destroy(Material $material)
{
    $material->delete();
    return back()->with('success', 'Material was deleted successfully.');
}

But if I use the $id instead the destroy method does work...

public function destroy($id)
{
    $material = Material::find($id);
    $material->delete();
    return back()->with('success', 'Material was deleted successfully.');
}

Steps To Reproduce:

I'm not sure if this is a bug or something that I'm doing wrong.

php artisan route:list

| Domain | Method    | URI                                          | Name              | Action                                                  | Middleware   |
+--------+-----------+----------------------------------------------+-------------------+---------------------------------------------------------+--------------+
|        | GET|HEAD  | /                                            |                   | App\Http\Controllers\PagesController@index              | web          |
|        | GET|HEAD  | api/user                                     |                   | Closure                                                 | api,auth:api |
|        | DELETE    | materials/{matirial}                         | materials.destroy | App\Http\Controllers\PatternMaterialsController@destroy | web          |
|        | GET|HEAD  | patterns                                     | patterns.index    | App\Http\Controllers\PatternsController@index           | web          |
|        | POST      | patterns                                     | patterns.store    | App\Http\Controllers\PatternsController@store           | web          |
|        | GET|HEAD  | patterns/create                              | patterns.create   | App\Http\Controllers\PatternsController@create          | web          |
|        | GET|HEAD  | patterns/{pattern}                           | patterns.show     | App\Http\Controllers\PatternsController@show            | web          |
|        | PUT|PATCH | patterns/{pattern}                           | patterns.update   | App\Http\Controllers\PatternsController@update          | web          |
|        | DELETE    | patterns/{pattern}                           | patterns.destroy  | App\Http\Controllers\PatternsController@destroy         | web          |
|        | GET|HEAD  | patterns/{pattern}/edit                      | patterns.edit     | App\Http\Controllers\PatternsController@edit            | web          |
|        | POST      | patterns/{pattern}/materials                 | materials.store   | App\Http\Controllers\PatternMaterialsController@store   | web          |
|        | GET|HEAD  | patterns/{pattern}/materials/{material}/edit | materials.edit    | App\Http\Controllers\PatternMaterialsController@edit    | web          |
|        | GET|HEAD  | patterns/{pattern}/matterials                | materials.index   | App\Http\Controllers\PatternMaterialsController@index   | web          |
+--------+-----------+----------------------------------------------+-------------------+---------------------------------------------------------+--------------+

for the resources/materials/index.blade.php. I haven't changed the blade file and but just changing the destroy method to utilize the $id instead of Material $material to make it work.

<form method="POST" action="{{ route('materials.destroy', [$material]) }}">
    @csrf @method('DELETE')
    <button type="submit" class="btn btn-danger btn-sm">Delete</button>
</form>

for the resource/patterns/show.blade.php

<form method="POST" action="{{ route('patterns.destroy', [$pattern]) }}" class="d-inline-block">
    @csrf @method('DELETE')
    <button type="submit" class="btn btn-danger btn-sm">Delete</button>
</form>

Most helpful comment

Hey there,

I guess your problem is inside your controller. You may have named your parameter as :
public function destroy(Material $material) { }
So the misnamed parameter will cause you a problem
what you have to do now is match your wildcard that is in your web file
with the parameter inside your controller

All 3 comments

You have

materials/{matirial}

but that should be

meterials/{material}

If you file your route file, that should solve the issue...

Hey there,

I guess your problem is inside your controller. You may have named your parameter as :
public function destroy(Material $material) { }
So the misnamed parameter will cause you a problem
what you have to do now is match your wildcard that is in your web file
with the parameter inside your controller

I love the outcome when another pair of eyes look at the code. The problem was the mismatch in web.php as @laurencei pointed out.

Was this page helpful?
0 / 5 - 0 ratings