0

I am using Laravel Framework 5.8.21. I am trying to bind an interface to a class based on Request params inside AppServiceProvider's register method like this.

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');
  }
}

and later injecting the interface to Controllers __construct() method.

with tests, it always bound to ClassName. I tried to get accessed URL inside AppServiceProvider and while running unit tests, it always returning / with $this->app->request->getRequestUri(); and method as GET even though from the test I am posting to URL like this.

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

While testing it with Postman, when I try to post http://localhost:8000/notification, it says, 419 | Page Expired.

Lakhwinder Singh
  • 5,536
  • 5
  • 27
  • 52
Mubin
  • 4,325
  • 5
  • 33
  • 55

2 Answers2

1

This is possible. The register method of AppServiceProvider or any other service provider has access to request parameters.

This can be accessed as follows:

public function register()
{
  $this->app->bind('SomeInterface', function($app) {
    return new SomeClass(request()->some_parameter);
  });
}
Tpojka
  • 6,996
  • 2
  • 29
  • 39
0

You will not be able to reliably use the current request information from within a service provider.

First, it is a general best practice to not depend on application logic within the register() method directly. You may cause a race condition where you have a dependency that hasn't been registered yet, or cause unnecessary overhead (e.g. establish a database connection even if you don't need any querying).

Second, Laravel's request lifecycle won't funnel the current request into the application until after all of the service provider registration and bootstrapping has been completed.

Without knowing exactly what business logic you're trying to accomplish, you have at least a couple options:

  1. Use contextual binding to serve different implementations of the same interface depending on the requesting object (e.g. controller).

  2. Use a factory or a similar facilitator-style object that you can inject in the controller, and can provide the proper dependency based on your preferred logic.

Aken Roberts
  • 13,012
  • 3
  • 34
  • 40