在我的laravel项目中,我有如下的接口、存储库和控制器。
这是接口
interface TrainingClassTypeInterfaces
{
public function updateTrainingClassType($id, $request);
}
这是仓库
use App\Models\Trainings\AppTrainingClassType;
class TrainingClassTypeEloquent implements TrainingClassTypeInterfaces
{
protected $model;
public function __construct(AppTrainingClassType $appTrainingClassType)
{
$this->model = $appTrainingClassType;
}
public function updateTrainingClassType($id, $request)
{
$response = false;
$isUpdated = $this->model::where('training_class_id',$id)->update([
'app_id' => $request->app_id
]);
....
}
}
这是控制器
class TrainingClassTypesController extends \TCG\Voyager\Http\Controllers\VoyagerBaseController
{
protected $trainingService;
public function __construct(TrainingClassTypeEloquent $trainingClassTypeInterfaces) {
$this->trainingService = $trainingClassTypeInterfaces;
}
public function insertOrUpdate()
{
...
$this->trainingService->updateTrainingClassType($id, $request);
..
}
}
一切正常工作到这里,
如您所见,我在TrainingClassTypesController
中使用TrainingClassTypeEloquent的方法。但是它返回的错误就像
Argument 1 passed to ...::__construct() must be an instance of
基本上,它要求我将模型的实例放入TrainingClassTypeEloquent
类。然后我做了如下
$TCTypes = new AppTrainingClassType();
$TCT = new TrainingClassTypeEloquent($TCTypes);
$TCT->updateTrainingClassType($id, $request);
这是很好的工作,但我感到困惑的是,这种方法是不适当的,应该有一些适当的方式。
在googling搜索之后,我找到了另一个解决方案,即单例绑定,然后我尝试在AppServiceProvider中使用
$this->app->singleton(
\App\Services\Voyager\Eloquent\TrainingClassType\TrainingClassTypeInterfaces::class,
\App\Services\Voyager\Eloquent\TrainingClassType\TrainingClassTypeEloquent::class
);
在添加了这个单例绑定之后,我注意到脚本正在工作,而没有向TrainingClassTypeEloquent
类提供模型实例。
我想知道$this->app->singleton()
是如何工作的,这样我的概念就清楚了。如果有人知道,请指导我。
非常感谢
发布于 2020-07-13 08:30:05
这一切都是关于绑定,一个服务到服务容器。
$this->app->singleton();
方法是干什么的?
单例方法将类或接口绑定到服务容器中,以便Laravel能够保持依赖关系(当使用接口作为构造函数参数时)。
(实际上,Singleton是一种设计模式。Singleton实现总是在后续调用时返回相同的对象,而不是一个新实例)。因此,$this->app->singleton();
方法一次又一次地返回同一个对象。
值得注意的是,说,Laravel:
如果类不依赖于任何接口,则不需要将它们绑定到容器中。不需要指示容器如何构建这些对象,因为它可以使用反射自动解析这些对象。
但是控制器类依赖于接口,因此容器需要被告知,要做到这一点,您需要使用这个$this->app->singleton();
方法,但是还有其他的方法。
同时,这个TrainingClassTypeEloquent::class
有一个AppTrainingClassType::class
的依赖项。但是在这种情况下,我们不需要担心这一点,因为Laravel使用反射API来维护它的依赖关系,因为这个类不像TrainingClassTypesController::class
类那样使用接口。
将服务绑定到容器之后,Laravel将自动将服务作为使用接口的构造函数方法的参数。
我希望这能帮到你。您可以从这个回答中找到更多的帮助。
发布于 2020-07-13 07:29:27
您需要注册TrainingClassTypeEloquent
$this->app->singleton(TrainingClassTypeInterfaces::class, static function ($app) {
return new TrainingClassTypeEloquent(new AppTrainingClassType());
});
然后你可以把它注入你的控制器
public function insertOrUpdate(TrainingClassTypeInterfaces $trainingService, $id)
{
$trainingService->updateTrainingClassType($id, request());
}
发布于 2020-07-13 11:05:19
结合单例
singleton
方法将类或接口绑定到只应该解析一次的容器中。一旦解析了单例绑定,将在随后调用容器时返回相同的对象实例:
$this->app->singleton('HelpSpot\API', function ($app) {
return new \HelpSpot\API($app->make('HttpClient'));
});
欲了解更多信息,请访问这里
https://stackoverflow.com/questions/62870556
复制相似问题