首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >$this->app->singleton()是如何在laravel中工作的?

$this->app->singleton()是如何在laravel中工作的?
EN

Stack Overflow用户
提问于 2020-07-13 06:46:42
回答 3查看 11.9K关注 0票数 5

在我的laravel项目中,我有如下的接口、存储库和控制器。

这是接口

代码语言:javascript
运行
复制
interface TrainingClassTypeInterfaces
{
    public function updateTrainingClassType($id, $request);
} 

这是仓库

代码语言:javascript
运行
复制
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
            ]);
            .... 
        }
    
    }

这是控制器

代码语言:javascript
运行
复制
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类。然后我做了如下

代码语言:javascript
运行
复制
$TCTypes = new AppTrainingClassType();
$TCT = new TrainingClassTypeEloquent($TCTypes);
$TCT->updateTrainingClassType($id, $request);

这是很好的工作,但我感到困惑的是,这种方法是不适当的,应该有一些适当的方式。

在googling搜索之后,我找到了另一个解决方案,即单例绑定,然后我尝试在AppServiceProvider中使用

代码语言:javascript
运行
复制
$this->app->singleton(
            \App\Services\Voyager\Eloquent\TrainingClassType\TrainingClassTypeInterfaces::class,
            \App\Services\Voyager\Eloquent\TrainingClassType\TrainingClassTypeEloquent::class
        );

在添加了这个单例绑定之后,我注意到脚本正在工作,而没有向TrainingClassTypeEloquent类提供模型实例。

我想知道$this->app->singleton()是如何工作的,这样我的概念就清楚了。如果有人知道,请指导我。

非常感谢

EN

回答 3

Stack Overflow用户

发布于 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将自动将服务作为使用接口的构造函数方法的参数。

我希望这能帮到你。您可以从这个回答中找到更多的帮助。

票数 2
EN

Stack Overflow用户

发布于 2020-07-13 07:29:27

您需要注册TrainingClassTypeEloquent

代码语言:javascript
运行
复制
$this->app->singleton(TrainingClassTypeInterfaces::class, static function ($app) {
    return new TrainingClassTypeEloquent(new AppTrainingClassType());
});

然后你可以把它注入你的控制器

代码语言:javascript
运行
复制
public function insertOrUpdate(TrainingClassTypeInterfaces $trainingService, $id)
{
    $trainingService->updateTrainingClassType($id, request());
}
票数 1
EN

Stack Overflow用户

发布于 2020-07-13 11:05:19

结合单例

singleton方法将类或接口绑定到只应该解析一次的容器中。一旦解析了单例绑定,将在随后调用容器时返回相同的对象实例:

代码语言:javascript
运行
复制
$this->app->singleton('HelpSpot\API', function ($app) {
    return new \HelpSpot\API($app->make('HttpClient'));
});

欲了解更多信息,请访问这里

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62870556

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档