Shaun Shaun - 4 months ago 118
PHP Question

Lavavel 5.2.36 MethodNotAllowedHttpException in RouteCollection.php line 218:

Hi I am fairly new to Laravel and am trying to implement a post request for a simple form. I have been following a YouTube Tutorial series (laravel 5 | Section 3 | Part 4 Routing POST Requests) however at 5:46mins in, there is a notification that this method is only applicable to versions prior to Laravel 5.2.

I have tried to edit the VerifyCsrfToken.php method protected $except = ['api/']; but this makes no difference.

My routes.php code snippet:

Route::post('/form-handler', function(\Illuminate\Http\Request $request){
if(isset($request['option']) && $request['firstName'])
{
if(strlen($request['firstName']) > 0){
return view('forms.formResults', ['action' => $request['option'], 'name' => $request['firstName']]);
}
return redirect()->back();
}
return redirect()->back(); // Return user back to the page they came from
})->name('form-handler');


My welcome.blade.php code snippet:

<div class="form-group">
<form action="{{route('form-handler')}}" method="post" class="form-control">
<label for="select-action">Select an option:</label>
<select id="select-action" name="option">
<option value="option1">Option1</option>
<option value="option2">Option2</option>
<option value="option3">Option3</option>
</select>
<input type="text" name="firstName">
<button type="submit">Submit Details</button>
<input type="hidden" value="{{Session::token()}}" name="_token"> <!-- Laravel Security Measure, Note name must always be '_token'-->
</form>
</div>


My full error message:

MethodNotAllowedHttpException in RouteCollection.php line 218:
in RouteCollection.php line 218
at RouteCollection->methodNotAllowed(array('POST')) in RouteCollection.php line 205
at RouteCollection->getRouteForMethods(object(Request), array('POST')) in RouteCollection.php line 158
at RouteCollection->match(object(Request)) in Router.php line 821
at Router->findRoute(object(Request)) in Router.php line 691
at Router->dispatchToRoute(object(Request)) in Router.php line 675
at Router->dispatch(object(Request)) in Kernel.php line 246
at Kernel->Illuminate\Foundation\Http\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 52
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in Debugbar.php line 49
at Debugbar->handle(object(Request), object(Closure))
at call_user_func_array(array(object(Debugbar), 'handle'), array(object(Request), object(Closure))) in Pipeline.php line 136
at Pipeline->Illuminate\Pipeline\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 32
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in CheckForMaintenanceMode.php line 44
at CheckForMaintenanceMode->handle(object(Request), object(Closure))
at call_user_func_array(array(object(CheckForMaintenanceMode), 'handle'), array(object(Request), object(Closure))) in Pipeline.php line 136
at Pipeline->Illuminate\Pipeline\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 32
at Pipeline->Illuminate\Routing\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 102
at Pipeline->then(object(Closure)) in Kernel.php line 132
at Kernel->sendRequestThroughRouter(object(Request)) in Kernel.php line 99
at Kernel->handle(object(Request)) in index.php line 53


Is this method of implementation completely invalid or does it just need a few tweeks?

Preferably I would like to know what the optimal post method is for retrieving form data, while still protecting your site from cross-site request forgeries.

Any fixes or alternate solutions will be much appreciated.

Please feel free to ask for any resources I may have left out.

Full routes.php (Note I have also tried adding the post method to the middleware route group):

<?php

/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It's a breeze. Simply tell Laravel the URIs it should respond to
| and give it the controller to call when that URI is requested.
|
*/

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

Route::get('/', 'WelcomeController@index')->name('home');

Route::resource('lists', 'ListsController');

Route::get('/contact/{firstName?}', function($firstName = null)
{
return view('about.contact', ['firstName' => $firstName]);
})->name('contact');

Route::get('/blog', function()
{
return view('blog.blog');
})->name('blog');

Route::group(['middleware' => 'auth'], function () {
Route::post('/form-handler', function(\Illuminate\Http\Request $request){
if(isset($request['option']) && $request['firstName'])
{
if(strlen($request['firstName']) > 0){
return view('forms.formResults', ['action' => $request['option'], 'name' => $request['firstName']]); // You create the view
}
return redirect()->back();
}
return redirect()->back(); // Return user back to the page they came from
})->name('form-handler');
});

Answer

Edited answer --

I have edited my answer to make cleaner code that has exactly what you need. instead of using isset, it uses validation that will not stop running the code if the options are not set. This will also display an error message on the blade view.

Your routes.php file should contain the following

Route::post('/form-handler', 'formController@formHandle');

The Blade view must have a form that looks like this

@if (count($errors) > 0)
    <div class="alert alert-danger">
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif
<div class="form-group">
    <form action="{{route('form-handler')}}" method="post" class="form-control">
        <label for="select-action">Select an option:</label>
        <select id="select-action" name="option">
            <option value="option1">Option1</option>
            <option value="option2">Option2</option>
            <option value="option3">Option3</option>
        </select>
        <input type="text" name="firstName">
        <input type="hidden" name="_token" value="<?php echo csrf_token(); ?>">
        <button type="submit">Submit Details</button>
        <input type="hidden" value="{{Session::token()}}" name="_token">
    </form>

The form controller must look like this

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Routing\Controller;

class FormController extends Controller
{
    /**
     * Logic Goes here.
     *
     * @param  Request  $request
     * @return Response
     */
    public function formHandle(Request $request)
    {   
        $this->validate($request, [
            'firstName' => 'required|min:1|max:255',
            'option' => 'required'
            ]);

            $data = $request;

            return view('forms.formResults')->compact($data);  
    }
}
Comments