El conde Lucanor's avatar

I can't understand why this basic store is returning an error?!

I'm trying to do a store, a simple and basic store.

And I keep getting the error The GET method is not supported for this route. Supported methods: POST.

My project is in Laravel 6, and here's the code:

web.php:

Route::post('store', 'enviarCurriculum\EnviarCurriculumController@store')
    ->name('store');

EnviarCurriculumController.php

public function store(StoreEnviarCurriculumPost $request)
{
				EnviarCurriculum::create($request->all());

				return view('mensaje_inscripcion');
}

StoreEnviarCurriculumPost

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StoreEnviarCurriculumPost extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        return [
            'nif' => 'required',
        ];
    }
}

enviar_curriculum.blade.php

<!DOCTYPE html>
<html lang="es">
// ...
<form action="{{ route('store') }}" method="POST" enctype="multipart/form-data">
			@csrf
			<label>NIF</label>

			<input type="text" name="nif" value="{{ old('nif') }}">

			@error('nif')
						<div style="color:white; background-color:red;">{{ $message }}</div>
			@enderror

			<label>Name</label>

			<input type="text" name="name" value="{{ old('name') }}">

			<input type="submit" class="enviar-formulario" value="Enviar">
</form>
//...
</html>

I tried to clear all the cache, routes, etc... and nothing, ALWAYS the same error.

Man, what's happening???

0 likes
21 replies
JussiMannisto's avatar

If you try to open the /store url in a browser, that's a GET request and you get this error.

You should not return a view as a response to a POST request. You should instead redirect to some GET route at the end.

This is slightly off-topic, but you shouldn't use $request->all() when creating a model. Use $request->validated() instead. The reason is that $request->all() includes all input - even parameters that weren't validated. Someone could slip in an id or something else.

I assume you'll add some extra validation to nif later. Right now it could be an integer, a string that's a million characters long, an array, etc.

1 like
El conde Lucanor's avatar

@JussiMannisto I tried to redirect to index blade too (a get route), look:

    public function store(StoreEnviarCurriculumPost $request)
    {
        EnviarCurriculum::create($request->all());

        return view('/');
    }
Route::get('/', 'enviarCurriculum\EnviarCurriculumController@index')
    ->name('index');

But nothing, it gives me exactly the same error, and the index route is a get.

What more can I do?

Respects to the validate I'll do later, I wanna solve first this strange error, but thanks for the tip!

JussiMannisto's avatar

@El conde Lucanor You're still returning a view. Return a redirect response instead:

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

or

return redirect('/');
1 like
El conde Lucanor's avatar

@JussiMannisto Sorry, I was not clear with my answer and copy pasted the last (desesperated) test, but yes, I have tried both return redirect('/'); and return redirect()->route('index');

But nothing, the same error :/

The thing is, in the url doesn't appear the "store", it's the /formulario route everytime, and if I do a dd(request->all()) the dd() doesn't appear too.

So, for some reason, I can't reach(?) the function store if one of the required fields (nif) of the StoreEnviarCurriculumPost is not filled in

JussiMannisto's avatar

@El conde Lucanor

So, for some reason, I can't reach the function store if one of the required fields (nif) of the StoreEnviarCurriculumPost is not filled in

That's what's supposed to happen. Your form request defines nif as required. So if nif is empty, it throws a validation exception and redirects you back automatically.

Let's start from the beginning: what route displays the enviar_curriculum.blade.php form view? Can you show the route definition and the controller method (if one exists)?

1 like
El conde Lucanor's avatar

@JussiMannisto Humm, ok, I understand the logic

Ok, this is the actual code of my web.php:

<?php

use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

// Route::get('/', function () {
//     return view('welcome');
// });

Route::get('/', 'enviarCurriculum\EnviarCurriculumController@index')
    ->name('index');
Route::post('plantilla', 'enviarCurriculum\EnviarCurriculumController@plantilla')
    ->name('plantilla');   
Route::post('formulario', 'enviarCurriculum\EnviarCurriculumController@formulario')
    ->name('formulario');
Route::post('store', 'enviarCurriculum\EnviarCurriculumController@store')
    ->name('store');

And the list of routes if I use php artisan route:list

|        | GET|HEAD | /          | index      | App\Http\Controllers\enviarCurriculum\EnviarCurriculumController@index      | web          |

|        | GET|HEAD | api/user   |            | Closure                                                                     | api,auth:api |

|        | POST     | formulario | formulario | App\Http\Controllers\enviarCurriculum\EnviarCurriculumController@formulario | web          |

|        | POST     | plantilla  | plantilla  | App\Http\Controllers\enviarCurriculum\EnviarCurriculumController@plantilla  | web          |

|        | POST     | store      | store      | App\Http\Controllers\enviarCurriculum\EnviarCurriculumController@store      | web 

Was this all you wanted to see or were you referring to something else?

JussiMannisto's avatar

@El conde Lucanor Yes. Which of those routes shows the enviar_curriculum.blade.php view?

1 like
El conde Lucanor's avatar

@JussiMannisto the "formulario" one:

web.php

Route::post('formulario', 'enviarCurriculum\EnviarCurriculumController@formulario')
    ->name('formulario');

EnviarCurriculumController.php

    public function formulario(Request $request)
    {
       // collecting data

            return view('enviar_curriculum', [
                // sending data
            ]);
        }
    }
JussiMannisto's avatar
Level 50

@El conde Lucanor Well there's your problem. It should be a GET route, not POST.

When you open a page in a browser by typing or clicking on a link, the browser sends a GET request to that URL. POST requests are for posting data to a server, often through a form. So all page routes should use GET.

Routes that handle form submissions should use POST, so your "store" route is correct. Just redirect to a GET route at the end.

1 like
El conde Lucanor's avatar

@JussiMannisto So, I should change to this?:

Route::get('formulario', 'enviarCurriculum\EnviarCurriculumController@formulario')
    ->name('formulario');
GET|HEAD | formulario | formulario | App\Http\Controllers\enviarCurriculum\EnviarCurriculumController@formulario | web  

Or where should I change it?

El conde Lucanor's avatar

@JussiMannisto Oh yeah it works! That was the problem!

Not only in the routes, in the previous blade to link the enviar_curriculum's one it was POST too.

I changed both to GET and now the custom request is working well! Hehe.

Thanks m8 ;)

Snapey's avatar

@El conde Lucanor No. That is not the right solution. Now all your form data is present in the URL bar because you are sending your form with a get request.

The flow should be

  • GET page to show form
  • POST the form to an endpoint, process the data and redirect to a GET route
  • GET the next page
  • POST the form to an endpoint, process the data and redirect to a GET route

So you should have a GET route to show the formulario form then a POST route for the fomulario data

Then a GET route to show the envarioCirriculum form then a POST route for the envarioCirriculum data

DONT try to do it all with GET routes.

Snapey's avatar

Sorry, but the elephant in the room ... Laravel 6 ?

El conde Lucanor's avatar

@Snapey Yes, unfortunately the PHP versions and several other elements of this company have meant that I can only program in Laravel 6 with no option to update it until later.

And respectly your second answer, there's no another <form> inside the .blade, look:

<!DOCTYPE html>
<html lang="es">
// ...
<form action="{{ route('store') }}" method="POST" enctype="multipart/form-data">
			@csrf
			<label>NIF</label>

			<input type="text" name="nif" value="{{ old('nif') }}">

			@error('nif')
						<div style="color:white; background-color:red;">{{ $message }}</div>
			@enderror

			<label>Name</label>

			<input type="text" name="name" value="{{ old('name') }}">

			<input type="submit" class="enviar-formulario" value="Enviar">
</form>
//...
</html>

The rest of code of this .blade are the typical html things (<head>, <body>, css, etc...)

Snapey's avatar

@El conde Lucanor with respect, if you // ... the content then noone can tell

El conde Lucanor's avatar

@Snapey Ok, I'll show you all the .blade content to make sure there is nothing wrong with that:

<!DOCTYPE html>
<html lang="es">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Enviar Currículum</title>
</head>

<body>
    <link href="{{ asset('css/enviar_curriculum.css') }}" rel="stylesheet">
    
    <div class="formulario">
        <div class="datos-principales">
            <div class="datos-convocatoria">
                <ul>
                    <li>
                        <h5>CONVOCATORIA</h5>
                        <p>{{ $idconvocatoria }}</p>
                    </li>

                    <li>
                        <h5>PROCESO</h5>
                        <p>{{ $idproceso }}</p>
                    </li>

                    <li>
                        <h5>CONVOCATORIA PROCESO</h5>
                        <p>{{ $idconvocatoriaproceso }}</p>
                    </li>
                </ul>
            </div>

            <div class="div-separador"></div>

        <div class="datos-formulario">
            <form action="{{ route('store') }}" method="POST" enctype="multipart/form-data">
                @csrf

                <input type="hidden" name="ID_convocatoria" id="{{ $idconvocatoria }}" value="{{ $idconvocatoria }}">
                <input type="hidden" name="ID_proceso" id="{{ $idproceso }}" value="{{ $idproceso }}">
                <input type="hidden" name="ID_convocatoria_proceso" id="{{ $idconvocatoriaproceso }}" value="{{ $idconvocatoriaproceso }}">
                {{-- De momento añado estos campos obligatorios para que no me salten errores, ver si hay que sustituirlos cara al futuro --}}
                <input type="hidden" name="num_registro_entrada" id="num_registro_entrada" value="0">

                <h2>Formulario de Contacto</h2>

                <p>Introduzca sus datos y nos pondremos en contacto lo antes posible</p>

                <table class="tabla-datos-personales-y-contacto">
                    {{-- Datos personales (Título) --}}
                    <tr>
                        <td colspan="2">
                            <h4>
                                Datos personales
                            </h4>
                        </td>
                    </tr>

                    {{-- NIF / NIE / Pasaporte + Nombre --}}
                    <tr style="vertical-align:top">
                        <td>
                            <label>
                                NIF / NIE / Pasaporte*
                            </label>

                            <br>

                            <input type="text" name="nif" id="nif" placeholder="NIF / NIE / Pasaporte" value="{{ old('nif') }}">

                            @error('nif')
                                <div style="color:white; background-color:red;">{{ $message }}</div>
                            @enderror
                        </td>

                        <td>
                            <label>
                                Nombre*
                            </label>

                            <br>

                            <input type="text" name="nombre" id="nombre" placeholder="Escriba su nombre" value="{{ old('nombre') }}">
                        </td>
                    </tr>
                </table>

                <input type="submit" class="enviar-formulario" value="Enviar">

                <br><br><br><br>
            </form>
        </div>
    </div>
</body>

</html>
Snapey's avatar

make sure your form is not nested inside another form

Snapey's avatar

open the browser network tools and check what happens when you click submit

Snapey's avatar

your form field is called "name" but your validation and error message is "nif"

so you are probably just getting redirected because of a validation error.

but the redirect does not work because Laravel is confused where to redirect because it will try to use the same name as the route you posted to but with a get.

what route displays the form and how did you get there?

As advised by @jussimannisto its broken because you return a view at the end of formulario

Please or to participate in this conversation.