Laravel 5 在查询生成器中无法访问路由绑定变量

Laravel 5 route binding variables not accessible in query builder

我正在使用路由绑定来确定 URL 的每个部分是否与前一个相关。我试图在我的查询构建器中访问路由 parameter/variable ($stage_number) 但没有成功。为了混淆事情,如果我用它工作的硬值替换变量,例如4

如何在查询中使用 $stage_number 变量?

/*
 * Route
 */
Route::get('/application/{application_id}/stage/{stage_number}', [
    'as' => 'application.stage',
    'uses' => 'ApplicationController@stage'
]);

/*
 * Route Service Provider
 */
// Application
$router->bind('application_id', function($application_id)
{
    $application = Application::find($application_id);

    if (! $application)
    {
        abort(404);
    }

    return $application;
});

// Stage
$router->bind('stage_number', function($stage_number)
{
    $application = $this->getCurrentRoute()->application_id;

    $stage = collect($application->stages)->where('order', $stage_number)->all();

    if (! $stage)
    {
        abort(404);
    }

    return $stage;
});

更新响应

感谢您提供有关在 collection 上致电 where() 的信息;我没有意识到它对查询构建器的处理方式不同。为 collection 更新我的 where() 效果很好 - 谢谢。但是,我在使用查询生成器时仍然遇到问题:

// Route with data
/application/1/stage/4

// Actual data returned
array:4 [▼
  0 => array:2 [▼
    "name" => "Information about the University or Education Course"
    "order" => 3
  ]
  1 => array:2 [▼
    "name" => "Information about your education to date"
    "order" => 4
  ]
  2 => array:2 [▼
    "name" => "Other Information"
    "order" => 5
  ]
  3 => array:2 [▼
    "name" => "Declaration"
    "order" => 6
  ]
]

// Desired data to be returned
array:1 [▼
  0 => array:2 [▼
    "name" => "Information about your education to date"
    "order" => 4
  ]
]

不管我在我的路线中指定什么 order 我似乎得到返回的所有内容 is not null 除非我选择 12 (这是没有的行订单号并从上面的数组示例中排除)然后我得到该行与所有其他行一起返回 is not null (如上例所示)但任何其他 null 行被排除在外。这是我Applicationobject上的关系问题吗?

public function stages()
{
    return $this->hasMany('App\Entities\Application\Stage', 'type_id')->orWhereNull('type_id')->orderBy('order', 'asc');
}

更新:

在我的关系中设置 foreign_keylocal_key 似乎解决了其他问题:

public function stages()
{
    return $this->hasMany('App\Entities\Application\Stage', 'type_id', 'type_id')->orWhereNull('type_id')->orderBy('order', 'asc');
}

您实际上是在 Collection 对象而不是 Builder 对象上调用 where() 方法。

Collection 上的 where() 方法略有不同。首先,它只能做相等比较。其次,默认情况下,它会进行严格的等于 (===) 比较,这是您的问题。由于您的 $stage_number 是一个字符串,而您的 order 字段很可能是一个整数,因此严格比较不会 return 任何结果。

您可以通过将 false 作为第三个参数传递,将比较更改为松等 (==)。您也可以使用 whereLoose() 方法,它做同样的事情。

另请注意,假设 stagesApplication 对象上的 hasManybelongsToMany 关系,则无需调用 collect(). $application->stages 已经 return 一个 Collection.

// pass false as third parameter
$stage = $application->stages->where('order', $stage_number, false)->all();

// or use whereLoose
$stage = $application->stages->whereLoose('order', $stage_number)->all();

现在,说了这么多,您可能想在查询生成器上调用 where()$application->stages 将提供 Collection 相关阶段对象,$application->stages() return 是关系的 Relation 对象,这使您可以访问查询构建器。由于您有权访问构建器,因此您可以将 where 子句添加到查询中 运行 并将提供性能提升(并且不关心变量类型)。

$stage = $application->stages()->where('order', $stage_number)->get();

请注意,get() 将 return 包含匹配舞台对象的 Collection 对象。如果 order 是唯一的并且你想获得那个阶段对象,你可以使用 first() 而不是 get():

$stage = $application->stages()->where('order', $stage_number)->first();