schellingerht
schellingerht

Reputation: 5796

Access Request in Service Provider After Applying Middleware

Bindings

I'm using bindings in my service provider between interface and implementation:

public function register()
{
    $this->app->bind('MyInterface', MyImplementation::class);
}

Middleware

In my middleware, I add an attribute to the request:

public function handle($request, Closure $next)
{
    $request->attributes->add(['foo' => 'bar]);
    return $next($request);
}

Now, I want to access foo in my service provider

public function register()
{
    $this->app->bind('MyInterface', new MyImplementation($this->request->attributes->get('foo')); // Request is not available
}

The register() is called before applying the middleware. I know.

I'm looking for a technique to 'rebind' if the request->attributes->get('foo') is set

Upvotes: 13

Views: 22204

Answers (4)

Bernard Wiesner
Bernard Wiesner

Reputation: 1425

The accepted answer is good, however it does not address the issues regarding DI. So in your Service Provider you need:

public function register()
{
    $this->app->bind('MyInterface', function () {
        return new MyImplementation(request()->foo);
    }
}

But you need to be careful with DI. If you do this in your Controller:

class MyController extends Controller
{
    public function __construct(MyInterface $myInterface)
    {
        $this->myInterface = $myInterface;
    }
}

It will NOT work! The constructor of the controller is called BEFORE the group middleware is applied, so the foo parameter will be null on MyImplementation.

If you want to use DI, you need to either resolve it using App::make(MyInterface::class) outside of the constructor, or even better pass your dependency in the Controller's method:

class MyController extends Controller
{
    public function index(MyInterface $myInterface)
    {
        $myInterface->getFoo();
    }
}

Above will work because the controller's method is executed after the middlewares are applied.

This is the flow of a laravel request:

  1. Global middleware run
  2. Target controller's __construct run
  3. Group middleware run
  4. Target controller's method/action run (in above case index)

Upvotes: 1

Adam Kozlowski
Adam Kozlowski

Reputation: 5896

In service provider You can also access Request Object by:

public function register()
{
    $request = $this->app->request;
}

Upvotes: 12

The Extendable
The Extendable

Reputation: 61

Try this

public function register()
{
    $this->app->bind('MyInterface', function ($app) {
        return new MyImplementation(request()->foo);
    }
}

Upvotes: 0

Filip Koblański
Filip Koblański

Reputation: 9988

Try like this:

public function register()
{
    $this->app->bind('MyInterface', function () {
        $request = app(\Illuminate\Http\Request::class);

        return app(MyImplementation::class, [$request->foo]);
    }
}

Binding elements works like this that they will be triggered only when they are call.

Upvotes: 29

Related Questions