【问题标题】:Binding to Laravel IoC instead of instantiating again and again绑定到 Laravel IoC 而不是一次又一次地实例化
【发布时间】:2019-02-12 13:52:36
【问题描述】:

在我的应用程序中,我有一个名为“LogService”的服务来记录事件和其他项目。我基本上需要在每个控制器上使用它来记录用户的事件。不必在每个控制器中实例化这个服务,我有两个想法来完成这个。

选项 1:将服务绑定到 IoC,然后以这种方式解析它

选项 2:创建一个包含服务的主类,然后为其他类扩展它,以便它们与已经绑定的服务一起提供

我对以下每种方法都有疑问:

选项 1:这甚至可能吗?如果是这样,它会被称为“App::make()”吗?这种方式似乎不太适合 IDE 的

选项 2:我过去做过这种事情,但 PHPStorm 似乎无法识别来自父对象的服务,因为它是由“App::make()”实例化的,而不是通过常规依赖注入。

最好的做法是什么?

谢谢!

【问题讨论】:

    标签: php laravel-5 phpstorm-2018.1


    【解决方案1】:

    两种方式都可以,我认为最简洁的方式是:

    1) 有一个描述你的类的接口,我们称之为LogServiceInterface

    2) 创建一个实例化您的类的服务提供者,如下所示:

    <?php
    
     namespace App\Providers;
    
     use Illuminate\Support\ServiceProvider;
    
     class LoggerServiceProvider extends ServiceProvider
     {
         /**
          * Register bindings in the container.
          *
          * @return void
          */
         public function register()
         {
             $this->app->bind(LogServiceInterface::class, function($app)
             {
                 return new LogService();
             });
         }
      }
    

    3) 在config/app.ph文件中注册该服务提供者:

    'providers' => [
        // Other Service Providers
    
        App\Providers\LoggerServiceProvider::class,
    ],
    

    4) 现在,在控制器中,您可以直接在构造函数中请求实现 LoggerServiceInterface 的实例:

    (某些控制器):

    <?php namespace App\Http\Controllers;
    
    use Illuminate\Routing\Controller;
    use App\Repositories\OrderRepository;
    
    class OrdersController extends Controller {
    
        /**
         * The logger service.
         * @var LoggerServiceInterface $loggerService
         */
        protected $loggerService;
    
        /**
         * Create a controller instance.
         *
         * @param  OrderRepository  $orders
         * @return void
         */
        public function __construct(LoggerServiceInterface $loggerService)
        {
            $this->loggerService = $loggerService;
        }
    
        /**
         * Show all of the orders.
         *
         * @return Response
         */
        public function index()
        {
            // $this->loggerService will be an instance of your LoggerService class that 
            // is instantiated in your service provider
        }
    
    }
    

    这样,您可以轻松快速地更改服务的实现,而且,Phpstorm 可以非常轻松地处理这个问题。

    您仍然可以使用app()-&gt;make() 来获取您的服务实例。 然而,这不会被 Phpstorm 自动拾取。但是你可以帮助它理解,你需要做的就是使用@var注解,见:

    /**
     * @var LoggerServiceInterface $logger
     */
     $logger = app()->make(LoggerServiceInterface::class);
    
    That way, Phpstorm will know what to expect from that $logger object.
    

    【讨论】:

    • 我认为这与我原来的问题没有太大不同。我错过了什么吗?如果我遵循这种模式,我将不得不将日志服务接口引入每个控制器。我想知道是否可以避免这样做。
    • 你仍然可以用 app()->make() 实例化它
    • 是的,但我认为 PHPstorm 不会在你这样做时捡起它,然后你不会得到代码提示,这不是最大的交易,但会很好。
    • 哦,我现在更清楚地看到了您的问题 :) 我更新了我的答案,希望对您有所帮助。 @ackerchez
    • 啊,我明白了。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2022-01-26
    • 2020-03-24
    • 1970-01-01
    • 2015-10-22
    • 1970-01-01
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    相关资源
    最近更新 更多