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
除非我选择 1
或 2
(这是没有的行订单号并从上面的数组示例中排除)然后我得到该行与所有其他行一起返回 is not null
(如上例所示)但任何其他 null
行被排除在外。这是我Application
object上的关系问题吗?
public function stages()
{
return $this->hasMany('App\Entities\Application\Stage', 'type_id')->orWhereNull('type_id')->orderBy('order', 'asc');
}
更新:
在我的关系中设置 foreign_key
和 local_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()
方法,它做同样的事情。
另请注意,假设 stages
是 Application
对象上的 hasMany
或 belongsToMany
关系,则无需调用 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();
我正在使用路由绑定来确定 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
除非我选择 1
或 2
(这是没有的行订单号并从上面的数组示例中排除)然后我得到该行与所有其他行一起返回 is not null
(如上例所示)但任何其他 null
行被排除在外。这是我Application
object上的关系问题吗?
public function stages()
{
return $this->hasMany('App\Entities\Application\Stage', 'type_id')->orWhereNull('type_id')->orderBy('order', 'asc');
}
更新:
在我的关系中设置 foreign_key
和 local_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()
方法,它做同样的事情。
另请注意,假设 stages
是 Application
对象上的 hasMany
或 belongsToMany
关系,则无需调用 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();