0

hoping that someone can help out.

I have all other methods (edit and new) working well with protected routes at this stage. It's just delete that is not playing nice. (although I'm sure it's something silly that I am doing). I have removed the auth by taking the delete out of the route group with the middleware assigned to it and it successfully deletes the config (object) so the action is working correctly. I try to check it in firebug as suggested in another post and I get:

405 Method Not Allowed

Allow           DELETE
Cache-Control   no-cache, private
Connection      close
Content-Type    text/html
Date            Wed, 11 Nov 2015 12:36:40 GMT
Host            127.0.0.1:8000
X-Powered-By    PHP/5.5.9-1ubuntu4.14

I would like to have the user authenticate before creating a new entry or editing an existing one (and likewise for delete).

When I try a delete by pressing the button, and it directs me to auth/login (out of the box quickstart auth for laravel) as it should, but then upon successful login, the url in the address bar is:

127.0.0.1:8000/delete/48

showing:

MethodNotAllowedHttpException in RouteCollection.php line 219:

routes.php:

Route::get('/new', [
    'as' => 'create', 
    'middleware' => 'auth',
    'uses' => 'ConfigsController@getCreate'
]);
$router->group(['middleware' => 'auth'], function($router)
    {
    Route::get('{id}/edit', 'ConfigsController@edit');
    Route::delete('/delete/{id}/', 'ConfigsController@getDL');
    });

+--------+----------+-------------------+----------+-------------------------------------------------------+------------+
| Domain | Method   | URI               | Name     | Action                                                | Middleware |
+--------+----------+-------------------+----------+-------------------------------------------------------+------------+
|        | DELETE   | delete/{id}       |          | App\Http\Controllers\ConfigsController@getDL          | auth       |
|        | POST     | new               |          | App\Http\Controllers\ConfigsController@postCreate     |            |
|        | GET|HEAD | new               | create   | App\Http\Controllers\ConfigsController@getCreate      | auth       |
|        | GET|HEAD | {id}/edit         |          | App\Http\Controllers\ConfigsController@edit           | auth       |

ConfigsController.php:

public function getCreate() {
return view('create');
}

public function edit($id)
{
$configs = Config::find($id);
    return view('edit')
    ->with('configs', $configs);
}

public function getDL($id) {
    $configs = Config::find($id)->delete();
    return Redirect::to('/');
}

index.blade.php (edit & delete) & app.blade.php (new):

<ul class="nav navbar-nav">
  <li><a href="{{ URL::route('create') }}">New</a></li>
</ul>

{!! Form::open(array('url' => '/delete/' . $config->id . '/', 'class' => 'pull-right')) !!}
{!! Form::hidden('_method', 'DELETE') !!}
{!! Form::submit('Delete this Config', array('class' => 'btn btn-warning')) !!}
{!! Form::close() !!}

<a class="btn btn-small btn-info" href="{{ URL::to('/' . $config->id . '/edit') }}">Edit this Config</a>
savager1
  • 61
  • 1
  • 9

1 Answers1

0

This is because Laravel authenticate() function out of box is using "intended" while redirecting.

What this means it that when user is not logged in and makes a get request at /whateverpage Laravel steps in and forces user to login, after successful login Laravel redirects user to "intended" page which is in our example /whateverpage and in your case /delete/48.

/**
* Send the response after the user was authenticated.
*
* @param  \Illuminate\Http\Request  $request
* @param  bool  $throttles
* @return \Illuminate\Http\Response
*/
protected function handleUserWasAuthenticated(Request $request, $throttles)
{
    if ($throttles) {
        $this->clearLoginAttempts($request);
    }

    if (method_exists($this, 'authenticated')) {
        return $this->authenticated($request, Auth::user());
    }

    return redirect()->intended($this->redirectPath());
}

This code is inside trait so you are looking for "override-ing" trait function.


Solution using $redirectPath

From this documentation section you can see that setting $redirectPath is what you need.

When a user is successfully authenticated, they will be redirected to the /home URI, which you will need to register a route to handle. You can customize the post-authentication redirect location by defining a redirectPath property on the AuthController: protected $redirectPath = '/dashboard';


Solution and cause

You get MethodNotAllowedHttpException because browsers can do only GET or POST requests; here is more information from Laravel documentation (form method spoofing).

HTML forms do not support PUT, PATCH or DELETE actions. So, when defining PUT, PATCH or DELETE routes that are called from an HTML form, you will need to add a hidden _method field to the form.

Since you are not using form to delete "configs" you have to use GET instead of DELETE

Route::delete('/delete/{id}/', 'ConfigsController@getDL'); Route::get('/delete/{id}/', 'ConfigsController@getDL');


Working example

$ php artisan route:list

+--------+----------+--------------------+---------------+--------------------------------------------------+------------+
| Domain | Method   | URI                | Name          | Action                                           | Middleware |
+--------+----------+--------------------+---------------+--------------------------------------------------+------------+
|        | GET|HEAD | config/create      |               | App\Http\Controllers\ConfigController@getCreate  | auth       |
|        | POST     | config/create      |               | App\Http\Controllers\ConfigController@postCreate | auth       |
|        | GET|HEAD | config/{id}/delete | config.delete | App\Http\Controllers\ConfigController@destroy    | auth       |
|        | GET|HEAD | config/{id}/edit   |               | App\Http\Controllers\ConfigController@getEdit    | auth       |
|        | POST     | config/{id}/edit   |               | App\Http\Controllers\ConfigController@postEdit   | auth       |
+--------+----------+--------------------+---------------+--------------------------------------------------+------------+

routes.php

Route::group(['middleware' => 'auth'], function () {
    Route::group(['prefix' => 'config'], function() {
        Route::get('create', 'ConfigController@getCreate');
        Route::post('create', 'ConfigController@postCreate');

        Route::get('{id}/edit', 'ConfigController@getEdit'); 
        Route::post('{id}/edit', 'ConfigController@postEdit');

        Route::get('{id}/delete', ['as' => 'config.delete', 'uses' => 'ConfigController@destroy']);
    });
});

and controller (note that it is renamed to ConfigController.php)

<?php namespace App\Http\Controllers;


use App\Config;

class ConfigController extends Controller {

    public function index()
    {
        // just show and sort, paginate... all config(s)
    }

    public function getCreate() {
        return view('create');
    }

    public function postCreate() {


    }

    public function getEdit($id, Config $config) { //injecting config model
        return view('edit')->with('config', $config->findOrFail($id));
    }

    public function postEdit($id, Config $config) {
        //do something with data that user sent us
        //Input::all();
        //$config->create([])


        //and redirect
        return Redirect::to('/');
    }

    public function destroy($id, Config $config) {
        $config->findOrFail($id)->delete();
        return Redirect::to('/');
    }

}

And to generate "delete link" with button

<a class="btn btn-small btn-warning" href="{{ route('config.delete', ['id' => $config->id]); }}">Delete</a>
Community
  • 1
  • 1
Kyslik
  • 8,217
  • 5
  • 54
  • 87
  • Thanks for your quick response @Kyslik. That's the thing, `$redirectPath` is already set `Auth/AuthController.php:` `protected $redirectPath = '/';` `protected $loginPath = 'auth/login';` – savager1 Nov 11 '15 at 18:41
  • Try to put it to your `ConfigsController.php` – Kyslik Nov 11 '15 at 18:51
  • Same result unfortunately @Kyslik. One thing I noticed in firebug was that: when not auth'd - with the process that's failing, i.e. redirect after successful login: firebug reports: GET 50, with Headers: Allow DELETE, so I am sending the wrong method? If I refresh the page after error and try to delete as auth'd delete then success with firebug reporting: POST 50 and then I can see the Post Params with method DELETE – savager1 Nov 11 '15 at 19:01
  • thanks I think I already have it in the: `{!! Form::hidden('_method', 'DELETE') !!}` The more I look at it I think it could be related to middleware...I think I need the route with after middleware perhaps...I'll let you know. Thanks for your help so far. – savager1 Nov 11 '15 at 19:20
  • Have you tried changing the route as I suggested? your method is even called "get" -> `@getDL` (also delete that _method...) It solves the "intended" part... – Kyslik Nov 11 '15 at 19:24
  • Yes, I did try the route change but still no joy, I tried delete the _method in the form but then I get the same error, it's not until I re-added, then I had a successful redirect to auth/login...but then same error. By the way, I was following this tutorial: https://scotch.io/tutorials/simple-laravel-crud-with-resource-controllers and then trying to "force" users to login before certain actions, such as new/edit/delete. – savager1 Nov 11 '15 at 19:54
  • See new edit :) working example. I assume your config model is in app/ folder if not change line #4 in ConfigController to match where your model is located. And also you will access your "config resource" thru `localhost/config/` – Kyslik Nov 11 '15 at 20:47
  • Thanks for that Kyslik, will try it out. If all good I'll mark as correct...but either way thanks for your help and putting up with me :) – savager1 Nov 11 '15 at 22:09
  • thank you soooooo much, that's awesome worked like a charm! :) thanks again for putting up with me. – savager1 Nov 11 '15 at 22:18