Laravel route/controller 参数如何工作?

How do Laravel route/controller parameters work?

我知道如果我有一个路由 say api/users/{id} 那么它将作为 $id 参数传递给控制器​​函数。

但是,如果我有一条 api 路线:

Route::patch('roadmap/{roadmapcourse}', 'RoadmapCourseController@update');

和控制器方法:

/**
   * Update the specified resource in storage.
   *
   * @param  \Illuminate\Http\Request  $request
   * @param  \App\RoadmapCourse $roadmapcourse
   * @return \Illuminate\Http\Response
   */
  public function update(Request $request, RoadmapCourse $roadmapcourse)
  {
    $data = $request->validate([
      'user_id' => 'required|integer',
      'course_id' => 'required|integer',
      'stage' => 'required|integer',
      'title' => 'required|string',
      'creator' => 'required|string',
      'url' => 'required|string',
      'hours' => 'required',
      'completed' => 'required|boolean'
    ]);

    $roadmapcourse->update($data);

    return response($roadmapcourse, 200);
  }

然后我向 http://projectname/api/roadmap/2 发送请求 - 然后 2 作为参数传递给更新函数,不是吗?

但是从更新函数的外观来看,它需要一个 RoadmapCourse 实例而不是单个数字,即“2”?

Laravel是否在幕后搜索 ID 为 2 的 RoadmapCourse 的数据库条目,然后将其作为 $roadmapcourse 引入函数中?

这是我唯一能想到的,我找不到任何文档来解释正在发生的事情。

P.S 我也找不到任何关于 Class $variable 的变量命名约定的文档,即 RoadmapCourse $roadmapcourse,我明白它的作用,只是找不到任何文档。

P.P.S 我也找不到任何解释控制器方法上方 "docblocks" 的文档,例如

/**
   * Update the specified resource in storage.
   *
   * @param  \Illuminate\Http\Request  $request
   * @param  \App\RoadmapCourse $roadmapcourse
   * @return \Illuminate\Http\Response
   */

这些“@param”声明的实际用途是什么?

任何帮助或文档链接将不胜感激(我一直在查看 Laravel 文档,但找不到任何提及或任何这些内容 - 因此在此处发布)

谢谢!

Does Laravel, behind the scenes, search for a database entry for a RoadmapCourse with the id of 2, and then bring that in to the function as $roadmapcourse?

是的,确实如此。有关详细信息,请参阅 https://laravel.com/docs/5.8/routing#route-model-binding

Since the $user variable is type-hinted as the App\User Eloquent model and the variable name matches the {user} URI segment, Laravel will automatically inject the model instance that has an ID matching the corresponding value from the request URI. If a matching model instance is not found in the database, a 404 HTTP response will automatically be generated.

至于其他问题(注意,以后尽量把问题限制在单一的、简洁的问题上),变量名无所谓; $roadmapcourse 可以是任何东西,只要注入的模型是正确的。如果您不使用 RoadmapCourse,它会根据主键(通常是 id)尝试查找您传递的任何模型。

对于 docblocks,这是标准函数注释。 @param@return 可以被解析并在 REST API 文档中显示这些值,但默认情况下,它们除了提供视觉参考外什么都不做。如果你愿意,你可以安全地忽略那些。

I understand that if I have a route of say api/users/{id} then this will get passed to the controller function as an $id param.

这是因为参数将存储为常规变量。

However if I have a api route of (...) and my controller looks like this:

public function update(Request $request, RoadmapCourse $roadmapcourse) { /** ... */ }

It doesn't work.

这是因为您正在尝试使用 Model Binding,但是给定您的变量名(和路由参数)Laravel 无法解析正确的 class。

如果改为这样做:

Route::patch('roadmap/{roadmapcourse}', 'RoadmapCourseController@update');
public function update(Request $request, $roadmapcourse)
{ //                                     ^^^^^^^^^^^^^^
    dd($roadmapcourse); // you'll get the value
}

当然,您可以告诉 laravel 正确解析路径变量以从数据库中获取记录。为此,您需要配置 Explicit Binding。来自文档:

Explicit Binding

To register an explicit binding, use the router's model method to specify the class for a given parameter. You should define your explicit model bindings in the boot method of the RouteServiceProvider class:

public function boot()
{
    parent::boot();

    Route::model('user', App\User::class);
}

Next, define a route that contains a {user} parameter:

Route::get('profile/{user}', function (App\User $user) {
    //
});

所以在你的情况下,试试这个:

# app/Providers/RouteServiceProvider.php

public function boot()
{
    parent::boot();

    Route::model('roadmapcourse', App\RoadmapCourse::class);
}

到时候,Laravel就能解析你的路由参数:

Route::patch('roadmap/{roadmapcourse}', 'RoadmapCourseController@update');