Laravel 5.4 路线简化

Laravel 5.4 route simplification

我一直在寻找一些关于如何完成以下任务的文档,但我似乎没有使用正确的搜索词。

我想在 Laravel 5.4 中实现一些简化的路由,方法是从路径中省略路由名称——例如:

  1. /{page} 而不是 /pages/{page}
  2. /profile 而不是 /users/{user}/edit
  3. /{exam}/{question}(甚至/exams/{exam}/{question})而不是/exams/{exam}/questions/{question}

当前路线示例

Route::resource('exams.questions', 'ExamQuestionController', ['only' => ['show']]);
// exams/{exam}/question/{question}

我知道如何使用路线封闭和一次性路线(例如:Route::get...)来做到这一点,但是有没有办法使用 Route::resource 来做到这一点?

rails 中,上述可以通过以下方式完成:

resources :exams, path: '', only: [:index, :show] do
  resources :question, path: '', only: [:show]
end

// /:exam_id/:id

不,你不能也不应该尝试用Route::resource来做这件事。

Route::resource 的全部目的是它以与通用 "RESTful Routing" 模式相匹配的特定方式创建路由。

想要更简单的路线并没有错(没有人强迫你使用 RESTful 路线),但是你需要自己用 Route::get 等来制作它们,正如你已经知道的那样.

来自 the documentation(不完全是你的情况,但与之相关 - 表明 Route::resource 并不意味着超级可配置):

Supplementing Resource Controllers

If you need to add additional routes to a resource controller beyond the default set of resource routes, you should define those routes before your call to Route::resource; otherwise, the routes defined by the resource method may unintentionally take precedence over your supplemental routes:

Route::get('photos/popular', 'PhotoController@method');

Route::resource('photos', 'PhotoController');

虽然我还没有找到一种方法来严格使用 Route::resource 来完成我的测试用例,但这是我为完成我想做的事情而实施的方法:

// For: `/{exam}/{question}`
Route::group(['as' => 'exams.', 'prefix' => '{exam}'], function() {
  Route::get('{question}', [
    'as'      => 'question.show',
    'uses'    => 'QuestionController@show'
  ]);
});

// For: `/exams/{exam}/{question}`
Route::group(['as' => 'exams.', 'prefix' => 'exams/{exam}'], function() {
  Route::get('{question}', [
    'as'      => 'question.show',
    'uses'    => 'QuestionController@show'
  ]);
});

// For: `/profile`
Route::get('profile', function() {
  $controller = resolve('App\Http\Controllers\UserController');
  return $controller->callAction('edit', $user = [ Auth::user() ]);
})->middleware('auth')->name('users.edit');

// For: `/{page}`
// -------------- 
// Note that the above `/profile` route must come before 
// this route if using both methods as this route
// will capture `/profile` as a `{page}` otherwise
Route::get('{page}', [
  'as'      => 'page.show',
  'uses'    => 'PageController@show'
]);