我最近刚刚开始学习 Laravel,并决定通过实践来学习。
据我从文档中了解到的[示例:1][示例:2]我可以在构造函数中键入提示属性以进行自动注入。
因此,为了尝试这一点,我决定重做微风脚手架的用户注册控制器,使其更加清晰,并将验证和所有逻辑提取到服务中。
class RegisteredUserController extends Controller
{
protected UserService $userService;
public function __construct(UserService $userService)
{
}
public function store(RegisterUserRequest $request): RedirectResponse
{
$this->userService->create($request->validated());
return redirect(route('dashboard', absolute: false));
}
}
服务非常简单,我只是从控制器的操作中复制粘贴默认代码:
class UserService
{
/**
* @param RegisterUserRequest $request
* @return void
*/
public function create(RegisterUserRequest $request): void
{
$user = User::create([
'name' => $request['name'],
'email' => $request['email'],
'password' => Hash::make($request['password']),
'age' => $request['age'],
]);
event(new Registered($user));
Auth::login($user);
}
到目前为止,这都是有趣的游戏,一切都按预期进行。所以我决定继续使用相同的模式,我讨厌臃肿的控制器,即使第一个方法可能不需要调用服务。但我计划添加更多。
class HousingService
{
/**
* @return Collection
*/
public function list(): Collection
{
return Housing::all();
}
}
我希望你还在我身边,抱歉让你拖了这么久。但我们现在正在解决这个问题。
当我尝试使用相同的方法将依赖的 HousingService 类注入到 HousingController 中时,我收到一条错误,提示我正在尝试在初始化之前访问类型化属性。
初始化之前不得访问类型化属性 App\Http\Controllers\HousingController::$housingService
这就是有问题的控制器。我完全不知道这两者有什么区别。
class HousingController extends Controller
{
protected HousingService $housingService;
public function __construct(HousingService $housingService)
{
//if i type the commented code below it fixes the error, but
//i'd like to know what's causing it, since it wasn't required
//before
//$this->housingService = $housingService
}
public function list(Request $request)
{
return view('housing.list', [
'user' => $request->user(),
'housings' => $this->housingService->list(),
]);
}
}
感谢您对我的包容,希望我不是一个绝对的白痴,因为错过了一些非常简单的东西。
您似乎将依赖注入与 OOP 混淆了。 DI 仅用于根据类型提示的类自动构建所需的对象,并将它们注入到当前方法中。您如何处理方法/类中的构建对象取决于您。
protected HousingService $housingService;
public function __construct(HousingService $housingService)
{
// here $housingService is the injected object from DI
// this injected object has nothing to do with the properties of the class
// $this->housingService is a property of the class and since you have not given it a default value it is an undefined property
// so $this->housingService and $housingService are not the same
// it is up to you to assign the property to the injected object
$this->housingService = $housingService
}
如果你不想写出来,较短的语法版本是:
public function __construct(protected HousingService $housingService)
{}
请记住,这只是语法糖,其功能与第一个版本相同。