Laravel 5:在RouteCollection.php中保护身份验证后的删除路由MethodNotAllowedH


Laravel 5: when protecting delete route after authentication MethodNotAllowedHttpException in RouteCollection.php

希望有人能帮忙。

在这个阶段,我有所有其他方法(编辑和新建)都能很好地处理受保护的路由。只是删除不太好。(尽管我确信我所做的事情很愚蠢)。我通过从路由组中删除分配给它的中间件来删除auth,它成功地删除了config(对象),因此操作正常。我试着在另一篇帖子中建议的firebug中检查它,我得到了:

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

我希望在创建新条目或编辑现有条目之前让用户进行身份验证(删除时也是如此)。

当我按下按钮尝试删除时,它会指示我进行身份验证/登录(开箱即用的laravel快速启动身份验证),但一旦成功登录,地址栏中的url为:

127.0.0.1:8000/delete/48

显示:

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>

这是因为Laravel authenticate()函数在重定向时使用了开箱即用的"intended"。

这意味着,当用户未登录并在/whateverpage发出get请求时,Laravel会介入并强制用户登录,在成功登录后,Laraver会将用户重定向到"预期"页面,在我们的示例中为/whateverpage,在您的示例中则为/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());
}

此代码位于trait内部,因此您正在寻找"覆盖"trait函数


使用$redirectPath的解决方案

从本文档部分,您可以看到设置$redirectPath正是您所需要的。

当用户成功通过身份验证时,他们将被重定向到/home URI,您需要注册一个路由来处理该URI。您可以通过在AuthController上定义redirectPath属性来自定义身份验证后重定向位置:protected $redirectPath = '/dashboard';


解决方案和原因

得到MethodNotAllowedHttpException是因为浏览器只能执行get或POST请求;以下是来自Laravel文档(表单方法欺骗)的更多信息。

HTML表单不支持PUT、PATCH或DELETE操作。因此,当定义从HTML表单调用的PUT、PATCH或DELETE路由时,您需要在表单中添加一个隐藏的_method字段。

由于您没有使用表单删除"配置",因此必须使用GET而不是delete

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


工作示例

$ 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']);
    });
});

和控制器(注意,它被重命名为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('/');
    }
}

并通过按钮生成"删除链接"

<a class="btn btn-small btn-warning" href="{{ route('config.delete', ['id' => $config->id]); }}">Delete</a>