Reputation: 1234
I got the following serivce provider:
class CartServiceProvider extends ServiceProvider {
public function boot() {
}
public function register() {
$this->app->singleton(\Alexxosipov\Cart\Cart::class, function($app) {
return new \Alexxosipov\Cart\Cart($app['request']);
});
}
}
And my Cart class, where I got this:
$this->id = (request()->cookie('cart_id')) ? request()->cookie('cart_id') : false;
But request()->cookie('cart_id')
returns encrypted string. If I will do it in any controller, it works fine. Why? What should I do to use it in Cart class?Laravel 5.5
Upvotes: 1
Views: 3473
Reputation: 8059
The sequences of Laravel bootstrapping a request is this (v5.6): (CMIIW)
index.php
is called\Illuminate\Foundation\Application
createdHttpKernel
registered. This register your middlewaresConsole Kernel
registered. This defines console commandsException Handler
registered. This defines exception handlersHttpKernel
instantiated. This instantiate all middlewares, plus boot/register all your service providersrequest
instance. Pass it to HttpKernel
to handle incoming request.EncryptCookies
called, cookies decryptedrequest
to other middlewares to processrequest
to router, router dispatch to controllerEncryptCookies
Cookie is remained encrypted in Step 1 - Step 7. Your CartServiceProvider
is trying to obtain a cookie that is yet to be decrypted at Step 6, which is not possible. Consider either
Decrypt the cookie by yourself (using just decrypt
), or
Make a middleware to instantiate the cart after EncryptCookies
. It's a little bit too early to instantiate cart at the bootstrapping service providers phase.
Edit: Add singleton suggestion
I think you could do this:
Create a new method named loadCartFromRequest($request)
in your Cart::class
. This method help you load a cart instance from request during the middleware phase.
In your CartServiceProvider
, you register a singleton of Cart::class
as usual, but no need to read the request here.
Create a middleware, called CartMiddleware
. This middleware call app(Cart::class)->loadCartFromRequest($request)
.
Then at any other places that you need the cart instance, you can access your cart model from app(Cart::class)
.
I hope I understand your requirement correctly :)
Upvotes: 5
Reputation: 35337
Why? Cookie encryption protects data stored in the client's browser.
The How: Laravel uses the EncryptCookies middleware, this middleware would not yet be processed when your service provider is registered but would be processed for the controller since middlewares are in the routing stack before the request is passed to the controller.
Since I don't know about your cart class and its logic, I can't really recommend what you should do. Perhaps you need to think about when you are passing the Request object to your class.
Upvotes: 4