BadMethodCallException Method [show] does not exist. Laravel

publicado por: Anonymous

Vengo realizando un CRUD en Laravel y me esta dando un error que no se localizar ya que no tengo ninguna funcion que se llame Show.

Userscontroller:

    public function destroy($id_usuario)
{
    $user = Usuario::find($id_usuario);
    $user->delete();

    Flash::warning('Se ha eliminado ' .$user->nombre . 'de forma correcta');
    return redirect()->route('users.index');
}

Index.blade.php

<a href="{{ route('users.destroy', $user->id_usuario) }}" class="btn btn-warning"><span class="glyphicon glyphicon-remove-circle" aria-hidden="true" onclick="return confirm('¿Seguro que quieres borrarlo')"></span></a>

Web.php

Route::group(['prefix' => 'admin'], function(){

Route::resource('users','Userscontroller');
Route::get('users/{id_usuario}/destroy', [
    'uses' => '[email protected]',
    'as'   => 'admin.users.destroy'
  ]);

});

solución

Cuando utilizas Route::resource() estás creando siete rutas a dicho controlador:

'index', 'create', 'store', 'show', 'edit', 'update', 'destroy'

Cada uno de estos métodos utiliza un verbo específico y un método en el controlador, como lo muestra el ejemplo de la documentación en PhotoController.

Verbo       URI                     Método  Nombre de la rta
GET         /photos                 index   photos.index
GET         /photos/create          create  photos.create
POST        /photos                 store   photos.store
GET         /photos/{photo}         show    photos.show
GET         /photos/{photo}/edit    edit    photos.edit
PUT/PATCH   /photos/{photo}         update  photos.update
DELETE      /photos/{photo}         destroy photos.destroy

Lo que ocurre en este caso es que al hacer clic en el enlace con ruta users/{id_usuario}/destroy y verbo GET, Laravel está encontrando la ruta de show /users/{id_usuario} generada por Route::resource() antes que la otra que creaste.

¿Por qué ocurre esto? Las rutas en Laravel se leen en “orden” de arriba hacia abajo, y al encontrar una coincidencia de verbo y si el paramétro “parcial” o completo encaja con la ruta, la utilizará.

En otras palabras, cuando haces clic en el enlace, Laravel revisa GET y luego encuentra una coincidencia en la ruta que llama al método show gracias a users/{id_usuario}, y el resto de la ruta (.../destroy) es ignorado.

SOLUCIONES:

  1. Utilizar el verbo DELETE al momento de hacer un destroy como lo sugiere Laravel, para esto harías un llamado al enlace con un formulario, algo así:

    {!! Form::open(['route' => ['users.destroy', $user->id_usuario], 'method' => 'DELETE']) !!}
      {!! Form::submit('Eliminar') !!}
    {!! Form::close() !!}
    
  2. Cambiar de orden las rutas para que Laravel encuentre primero tu ruta que la de resource:

    Route::get('users/{id_usuario}/destroy', [
        'uses' => '[email protected]',
        'as'   => 'admin.users.destroy'
    ]);
    Route::resource('users','Userscontroller');
    
  3. Decirle a Laravel que no genera la ruta que utiliza el método show:

    Route::resource('users','Userscontroller', ['except' => ['destroy', 'show']]);
    

Más información en la documentación: https://laravel.com/docs/5.4/controllers#resource-controllers

Respondido por: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *