【问题标题】:Laravel change binding with Request paramsLaravel 使用请求参数更改绑定
【发布时间】:2019-10-29 07:38:30
【问题描述】:

我正在使用Laravel Framework 5.8.21。我正在尝试将interface 绑定到基于AppServiceProviderregister 方法中的Request 参数的类,如下所示。

public function register()
{
  $this->app->bind('App\Contracts\SomeInterface', 'App\Logic\ClassName');
  if(Request::has('notification_type') && Request::get('notification_type') == 'email') {
    $this->app->bind('App\Contracts\SomeInterface', 'App\Logic\SomeotherClassName');
  }
}

然后将接口注入Controllers __construct() 方法。

通过测试,它总是绑定到ClassName。我试图在AppServiceProvider 中获取访问的 URL,并且在运行unit tests 时,它总是返回/$this->app->request->getRequestUri();,方法为GET,即使从测试中我发布到这样的URL。

$this->post('/notification', [
            'notification_type' => 'email',
  ])->assertJson(   
     'message-push-status' => true,
  ]);

在使用 Postman 对其进行测试时,当我尝试发布 http://localhost:8000/notification 时,它会显示 419 | Page Expired.

【问题讨论】:

    标签: php laravel laravel-5 dependency-injection service-provider


    【解决方案1】:

    您将无法可靠地使用来自服务提供商内部的当前请求信息。

    首先,一般的最佳实践是不直接依赖register() 方法中的应用程序逻辑。您可能会导致竞争条件,其中您的依赖项尚未注册,或者导致不必要的开销(例如,即使您不需要任何查询,也要建立数据库连接)。

    其次,Laravel's request lifecycle 不会将当前请求汇集到应用程序中,直到所有服务提供商注册和引导都已完成。

    在不确切知道您要完成的业务逻辑的情况下,您至少有几个选择:

    1. 使用contextual binding 为同一接口的不同实现提供服务,具体取决于请求对象(例如控制器)。

    2. 使用可以注入控制器的工厂或类似的促进器样式对象,并且可以根据您的首选逻辑提供适当的依赖关系。

    【讨论】:

      【解决方案2】:

      这是可能的。 AppServiceProvider 或任何其他服务提供者的 register 方法可以访问请求参数

      可以通过以下方式访问:

      public function register()
      {
        $this->app->bind('SomeInterface', function($app) {
          return new SomeClass(request()->some_parameter);
        });
      }
      

      【讨论】:

        猜你喜欢
        • 2016-08-17
        • 2015-04-20
        • 1970-01-01
        • 1970-01-01
        • 2021-06-24
        • 2020-06-11
        • 1970-01-01
        • 2016-07-03
        • 2017-05-20
        相关资源
        最近更新 更多