10
respostas

Problema ao passar id para rota de delete

Olá,

Estava refazendo o projeto do curso e desta vez decidi usar o padrão do Resource Contoller, no entanto estou com um problema :

Esta é a minha função destroy (chamada quando chamo a rota /series/{id} com metodo delete)

    public function destroy(Request $request){
        Serie::destroy($request->id);

        $request->session()->flash(
            'mensagem',
            "A Série {$request->nome} foi removida com sucesso!"
        );

        return redirect()->route('series.index');
    }

Este é o form em que é gerado a requisição que chega a este metodo:

<ul class="list-group">
    @foreach ($series as $serie)
    <li class="list-group-item">
        {{$serie->nome}}
    <form method="post" action="/series/{{$serie->id}}" onsubmit="return confirm('Tem certeza que deseja remover {{$serie->nome}} ?')">
            @csrf
            @method("delete")
            <button class="btn btn-danger" href="">Excluir</button>
        </form>
    </li>
    @endforeach
</ul>

O problema é que o array de parametros que chega ao metodo contem apenas elementos deste tipo e não o id da série como seria o esperado:

array:2 [▼
  "_token" => "EfFsyLuoMuQcgIFXro0DpbV6OipyR79hIBuS4Kx8"
  "_method" => "delete"
]

Ps. O Id chega ao form, tanto que se eu colocar um {{$serie->id}} em qualquer lugar dentro do foreach ele é exibido corretamente.

10 respostas

Daniel,

tente alterar o código da linha:

return redirect()->route('series.index');

para

return redirect()->route('listar_series');

ou

return redirect('/series');

Olá Adonai,

Obrigado por responder!

Eu testei sua sugestão, mas permaneci com o mesmo erro. Acredito que o problema ocorre antes do redirecionamento, já o que está ocorrendo é que a request não está chegando com os parametros no metodo do controller (embora eles estejam disponiveis no arquivo .blade em questão).

Ps.

return redirect()->route('series.index');

Está correto pois estou utilizando o controller Resources do próprio Laravel, conforme a documentação em : https://laravel.com/docs/5.8/controllers#resource-controllers

Meu arquivo web.php em routes tem apenas uma linha :

Route::resource('/series', 'SeriesController');

Olá, Daniel.

No Resource Controller você já recebe a model montada, e não o $id.

Logo, seu método pode ficar assim:

    public function destroy(Request $request, Serie $serie)
    {
        $serie->delete();

        $request->session()->flash(
            'mensagem',
            "A Série {$request->nome} foi removida com sucesso!"
        );

        return redirect()->route('series.index');
    }

Olá Vinicius,

Fiz essa alteração, inclusive criei um novo controller pelo artisan e de fato ele já trouxe o método destroy recebendo Serie como parâmetro.

 /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Serie  $serie
     * @return \Illuminate\Http\Response
     */
    public function destroy(Request $request, Serie $serie)
    {
                $serie->delete();
                dd($serie->id);

                $request->session()->flash(
                    'mensagem',
                    "A Série {$request->nome} foi removida com sucesso!"
                );

                return redirect()->route('series.index');
    }

O problema é que continua não acontecendo a deleção. O metodo destroy é chamado corretamente mas o que chega pra ele como parâmetro não está correto. Abaixo o retorno do metodo dd() na variável $serie.

Serie {#215 ▼
  #table: "series"
  #fillable: array:1 [▼
    0 => "nome"
  ]
  #connection: null
  #primaryKey: "id"
  #keyType: "int"
  +incrementing: true
  #with: []
  #withCount: []
  #perPage: 15
  +exists: false
  +wasRecentlyCreated: false
  #attributes: []
  #original: []
  #changes: []
  #casts: []
  #dates: []
  #dateFormat: null
  #appends: []
  #dispatchesEvents: []
  #observables: []
  #relations: []
  #touches: []
  +timestamps: true
  #hidden: []
  #visible: []
  #guarded: array:1 [▼
    0 => "*"
  ]
}
}

Olá, Daniel.

Um erro diferente significa avanço. hahahaha

Se você executa dd($serie->id) antes de executar o delete, vem o ID correto? Caso continue com erro, consegue executar no seu banco um SELECT pra garantir que o ID sendo passado realmente existe no banco?

Confesso que nunca tive esse problema...

Vinicius,

Resolvi o problema, o segredo estava nos detalhes kkkk

Reparando na documentação , a rota de deleção tem o seguinte caminho " /photos/{photo} ", onde esse "photo" é o nome do recurso que passamos quando instanciamos o Resource. Acontece que no web.php essa instanciação estava na forma que postei anteriormente:

Route::resource('/series', 'SeriesController');

O que fiz então foi remover a barra:

Route::resource('series', 'SeriesController');

E no formulário, embora o exemplo da documentação de a entender que devemos passar todo o objeto ($serie) como parâmetro eu testei fazer isso mas quando tentava extrair o id (fazendo $request->series->id) não funcionou. Passei a enviar apenas o id e funcionou conforme o código abaixo:

Meu metodo destroy ficou da seguinte forma (Fiz até a aula 3 do curso 2):

 public function destroy(Request $request,RemovedorDeSerie $removedorDeSerie)
    {
                $nome = $removedorDeSerie->removerSerie($request->series);

                $request->session()->flash(
                    'mensagem',
                    "A Série {$nome} foi removida com sucesso!"
                );

                return redirect()->route('series.index');
    }

Onde, $request->serie é apenas o id da serie vindo do formulário.

Ps. Ainda me ficou uma dúvida, se eu substituir o parametro Request no metodo acima pelo request que criamos simplesmente não funciona, ao clicar no botão de excluir a index é recarregada e nada mais acontece (sem mensagem de erro de qualquer natureza), porquê isso ?

2 coisas, Daniel.

1ª: $request->series realmente pegaria só o ID. Pra pegar a série completa você precisa tipar seu parâmetro: (Request $request, Serie $serie)

Assim, o parâmetro $serie já viria com a série montada.

2ª: Quanto ao erro com o FormRequest, aparece algum log no seu console? Nos logs do Laravel (storage/logs) aparece algo?

Ok Vinicius, Sobre a 1º obs: Não estou conseguindo receber um model de Serie como eu pensei que seria aconteceria:

Recapitulando, esta é minha função destroy:

public function destroy(Request $request,Serie $serie,RemovedorDeSerie $removedorDeSerie)

No blade que envia para este objeto eu tenho isso:

<form method="post" action="/series/{{$serie}}" onsubmit="return confirm('Tem certeza que deseja remover {{addslashes($serie->nome)}} ?')">
                @csrf
                @method("DELETE")

No corpo da destroy, se eu fiz isso:

dd($request->series);

Obtenho uma saída na forma de uma String :

"{"id":13,"nome":"Brokling 99","created_at":"2019-05-10 17:44:18","updated_at":"2019-05-10 17:44:18"}"

Se eu fiz isso:

dd($serie);

Recebo esse objeto que não sei bem dizer do que se trata, mas não é o que eu esperava pois eu não sei como obter os parâmetros da respectiva serie com ele.

Serie {#217 ▼
  #table: "series"
  #fillable: array:1 [▼
    0 => "nome"
  ]
  #connection: null
  #primaryKey: "id"
  #keyType: "int"
  +incrementing: true
  #with: []
  #withCount: []
  #perPage: 15
  +exists: false
  +wasRecentlyCreated: false
  #attributes: []
  #original: []
  #changes: []
  #casts: []
  #dates: []
  #dateFormat: null
  #appends: []
  #dispatchesEvents: []
  #observables: []
  #relations: []
  #touches: []
  +timestamps: true
  #hidden: []
  #visible: []
  #guarded: array:1 [▼
    0 => "*"
  ]
}

Sobre a 2º Obs, tenho o seguinte:

Isso funciona normal

public function destroy(Request $request,Serie $serie,RemovedorDeSerie $removedorDeSerie)

Apenas mudar o Request para isso:

public function destroy(SeriesFormRequest $request,Serie $serie,RemovedorDeSerie $removedorDeSerie)

Faz com que ao clicar no botão a pagina index apenas seja recarregada, o detalhe é que já testei deixar destroy sem nenhum uso do request dentro, ou seja já testei deixando só uma chamada echo() e também deixando um redirect para outra pagina que não a index. Ou seja, acredito que essa mudança na assinatura do metodo tá fazendo com que ele não seja chamado de fato.

Mas... isso me deixa em dúvida pois por SeriesFormRequest herdar de FormRequest eu imagino que ele deveria ser aceito e também no mesmo controller eu tenho o metodo store que tem a seguinte assinatura:

public function store(SeriesFormRequest $request, CriadorDeSerie $criadorDeSerie)

E isso funciona normalmente (a validação é executada).

Putz, Daniel. Dentre tantas mensagens eu acabei me distraindo e ignorei a parte mais importante. Vamos lá.

Você está tentando utilizar o SeriesFormRequest que valida se o nome da série, a quantidade de temporadas e o número de episódios por temporada foram enviados.

Mas no request pro método destroy, nenhum desses dados é enviado. Apenas o ID é enviado pela URL. O SeriesFormRequest tem a validação dos dados para criar a série.

Logo, o seu método nem chega a ser executado, porque a verificação falha e você é redirecionado de volta para a página anterior (a index).

Entendeu o problema?

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software