Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 491
schellingerht Avatar asked May 31 '16 20:05

schellingerht


3 Answers

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.

like image 179
Filip Koblański Avatar answered Oct 04 '22 13:10

Filip Koblański


In service provider You can also access Request Object by:

public function register()
{
    $request = $this->app->request;
}
like image 41
Adam Kozlowski Avatar answered Oct 04 '22 15:10

Adam Kozlowski


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)
like image 20
Bernard Wiesner Avatar answered Oct 04 '22 13:10

Bernard Wiesner