【问题标题】:Should I run database queries while binding in a Laravel Service Provider?我应该在绑定 Laravel 服务提供程序时运行数据库查询吗?
【发布时间】:2021-05-21 19:24:51
【问题描述】:

以下基本上是我现在所拥有的,它似乎正在工作。但是我发现有人说你不应该在服务提供者中运行数据库查询,因为并不是所有的东西都可以注册。以这种方式进行配置是否存在潜在问题?如果是这样,是否有另一种方法来设置我从数据库中获取配置数据的类似情况?

我最初是使用配置文件来绑定我想要的对象的实例

config/payment.php

'test' => array(
    'terminalid' => env('TERMINAL'),
    'secret' => env('SECRET'),
),

PaymentServiceProvider在注册方法中

  public function register()
  {
      $this->app->bind(Gateway::class, function ($app) {
          $gateway = new Gateway();
          return $gateway->initialize([
              config('payment.test')
          ]);
      });
  }

但我想更改它以使配置基于数据库查询。

设置表

license terminal secret
test ABC123 XXXX
demo ZYX987 XXXY

像这样的

  public function register()
  {
      $this->app->bind(Gateway::class, function ($app) {
          $setting = Setting::where("id",request()->id)->first();
          $gateway = new Gateway();
          return $gateway->initialize([
              'terminalid' => $setting->terminal,
              'secret' => $setting->secret,
          ]);
      });
  }

【问题讨论】:

  • 我很想知道你为什么要这样做。配置通常是环境绑定的,最好在环境变量或其他类型的全局配置中进行。
  • 我们有一个动态的公司列表,除了网关的凭据外,其他所有内容都相同。我会将所有内容都保留为配置数组,但我们经常添加公司以使数据库记录看起来更合适
  • 啊,像这样,我认为为此创建一个中间件会更好。假设您是在处理请求而不是实例化(至少在这个用例中看起来是这样)。
  • 是的,我正在使用请求变量来确定要使用的配置。什么是等效的中间件?我会在请求中将配置添加为变量吗?
  • 一个中间件实际上是在处理一个请求。因此,您拥有所有必要的请求变量,而无需调用辅助函数。它可以让你中断请求,在任何情况下出现问题。对于加载动态配置,这将更适合此用例。拦截请求并采取行动会更安全。因为您只会在需要时调用它,而不是始终存在于您的应用程序中。

标签: laravel service-provider


【解决方案1】:

我认为您可以将代码从 register 方法移动到 boot 方法

public function boot() {
   $this->app->bind(Gateway::class, function ($app) {
      $setting = Setting::where("id",request()->id)->first();
      $gateway = new Gateway();
      return $gateway->initialize([
         'terminalid' => $setting->terminal,
         'secret' => $setting->secret,
      ]);
   });         
}

因此,您将确定所有需要的服务都已注册

【讨论】:

  • 据我了解,启动方法在所有注册方法运行后运行。所以这应该有效。做这种方法或事情是否有任何潜在的副作用?
  • 据我所知,这样做没有副作用。这不是传统的。因为假设你在 register 方法中注册 (bind(), singleton()),并在 boot() 方法中进行一些初始化。但在你的情况下,你想要一些动态行为,所以应该没问题
【解决方案2】:

这可能会迟到,但我认为有一天它可能会帮助一个神奇的灵魂。

根据laravel documentation 和@nickc 的贡献,在服务提供者类的boot method 中运行代码是合适的。 但是,对于依赖于另一个服务提供者的服务提供者,正如您所解释的,您希望从数据库中读取配置。在我的发现中,无论订单注册如何,所有已注册的提供商都不一定可用。

注册的顺序很重要。

这是我的测试代码:

` /* * 应用服务提供商... */ App\Providers\AppServiceProvider::class, App\Providers\AuthServiceProvider::class, // App\Providers\BroadcastServiceProvider::class, App\Providers\EventServiceProvider::class, App\Providers\RouteServiceProvider::class,

    App\Providers\SchoolServiceProvider::class,

in my test AppServiceProvider depends on SchoolServiceProvider and SchoolServiceProvider depends onIlluminate\Database\DatabaseServiceProvider::class,` 位于提供程序列表的顶部。在我切换顺序并解决问题之前,这种方法不起作用。

` /* * 应用服务提供商... */ App\Providers\SchoolServiceProvider::class,

    App\Providers\AppServiceProvider::class,
    App\Providers\AuthServiceProvider::class,
    // App\Providers\BroadcastServiceProvider::class,
    App\Providers\EventServiceProvider::class,
    App\Providers\RouteServiceProvider::class,

` 我不知道为什么会这样,但这是我的发现。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-08
    • 1970-01-01
    • 2023-01-04
    相关资源
    最近更新 更多