在Laravel控制器中,如果所有的函数都使用Request,那么直接在构造函数中注入Request而不是函数是正确的?
下面的代码工作,我只是想知道它是否正确,如果它有副作用…
class BananaController extends Controller
{
protected $request; // request as an attribute of the controllers
public function __construct(Request $request)
{
$this->middleware('auth');
$this->request = $request; // Request becomes available for all the controller functions that call $this->request
}
public function store()
{
$this->validate($this->request, [
'text' => 'required',
]);
// I save the banana attributes and the controller continues...
放轻松点,关于stackoverflow的第一个问题:-)
[附录]为明确起见,"常规"代码为:
class BananaController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function store(Request $request)
{
$this->validate($request, [
'text' => 'required',
]);
// I save the banana attributes and the controller continues...
我一直在使用相同的技术来保护请求的所有资源控制器路由(例如检查登录用户是否被授权访问此资源)
然而,从Laravel 5.3开始,控制器构造函数现在在中间件执行之前运行,它实际上在请求中破坏了路由模型绑定。
因此,如果你直接将请求注入到控制器方法中,就像在Laravel文档中一样,如果你有任何模型绑定到你的路由,它会很好地解决它,但如果你在控制器构造函数中注入请求并尝试像下面这样在请求中访问你的模型,它将返回资源id而不是模型。
//Route service provider
Route::model('resource', MyModel::class);
//Request class
public function authorize()
{
//We expect to get a resource or null
//But now it just returns the resource id
if (!is_null($this->resource))
{
return $this->resource->createdBy->id == $this->getLoggedUser()->id;
}
}
如果您的控制器BananaController
中的所有或几乎所有方法都使用Request
类,那么注入依赖关系的最常见方法是通过类的构造函数,如您的示例所示。
如果依赖项是必需的,并且类没有它就不能工作,那么通过构造函数注入它可以确保在类使用时它是存在的,因为类没有它就不能构造。
构造函数只在对象创建时被调用一次,所以你可以确保依赖关系在对象的生命周期内不会改变。
注意,这些优点意味着构造函数注入不适合处理可选依赖。它在与类层次结构结合使用时也更加困难:如果一个类使用构造函数注入,那么扩展它并覆盖构造函数就会出现问题。
如果您使用construct函数来验证或授权,则不能再使用php artisan route:list
。所以最好通过路由模型绑定