Laravel obtains the current Guard analysis-from the actual needs of E-commerce shopping carts, laravel e-commerce

Source: Internet
Author: User

Laravel obtains the current Guard analysis-from the actual needs of E-commerce shopping carts, laravel e-commerce

The shopping cart requirements in iBrand are complex. We have expanded a shopping cart that better meets the needs of E-commerce based on overture/laravel-shopping-cart. Some Articles have previously made a simple introduction: laravel shopping cart: an e-commerce shopping cart that is running online.

Source Code address: ibrand/laravel-shopping-cart
Original Requirement

This package was initially extended due to the following requirements:

  • The user's shopping cart data after login needs to be stored in the database. Because the customer wants to intuitively see the product information in the current shopping cart, so as to push the discount information to promote conversion. Although we passed the data according to GA standards, we found that the data in GA was not very accurate.
  • User shopping cart data in the mall
  • Shopping guide uses shopping guide mini-programs to place orders on behalf of users or add shopping cart data during checkout, and does not synchronize with the user shopping cart data.
Original Solution

When the first requirement came out, we used different Guard to differentiate the user shopping cart data. Because the shopping mall and shopping guide were two different user systems, the code in the shopping cart ServiceProvider was as follows:

            $currentGuard = null;            $user = null;            $guards = array_keys(config('auth.guards'));            foreach ($guards as $guard) {                if ($user = auth($guard)->user()) {                    $currentGuard = $guard;                    break;                }            }            if ($user) {                //The cart name like `cart.{guard}.{user_id}`: cart.api.1                $cart->name($currentGuard.'.'.$user->id);            }else{                throw new Exception('Invalid auth.');            }

Traverse all existingGuardsTo obtain the guard value and user object of the current user in the request. Originally, when the new demand is not increased, everything runs normally.

New requirements

New requirements in 18 years:

  • The shopping cart data for self-ordering by the user's store QR code (QR code or barcode) should be differentiated from the shopping cart data of the mall.

That is, three types of Shopping Cart data exist.

  • User's shopping cart data in the mall
  • User shopping cart data for self-service orders in offline stores
  • Shopping Cart data
New demand Solution

When a new requirement arises, to distinguish the shopping cart data, you must create a new guard directly.config/auth.phpAddedshop guardThe Code is as follows.

'guards' => [        'web' => [            'driver' => 'session',            'provider' => 'users',        ],        'admin' => [            'driver' => 'session',            'provider' => 'admins',        ],        'api' => [            'driver' => 'passport',            'provider' => 'users',        ],        'shop' => [            'driver' => 'passport',            'provider' => 'users',        ],        'clerk' => [            'driver' => 'passport',            'provider' => 'clerk',        ],    ],
Problem generation

I thought it would run well, but we ignored a detail,apiAndshopThe two guard providers are the same, because they belong to users, andapiIt is also defined inshopSo when the following code is executed, the problem occurs becauseauth('api')->user()And then quit.shop guardThe data will also be storedapi guard.

           foreach ($guards as $guard) {                if ($user = auth($guard)->user()) {                    $currentGuard = $guard;                    break;                }            }
Solution

Engineers did not find an appropriate method before, so they used loop traversal guards to determine that the current request has been authenticated guard. When new requirements are generated, this method is no longer applicable, however, you cannot make major changes to the current shopping cart package, so you have to find a solution,

Ideas

In Laravelrequest()->user()Will get the correct authenticatedguard userData, so the preparation decided to start from the source code here.

Source code analysis

request()->user()The actual called code isIlluminate\Http\RequestIn classuser()Method

    public function user($guard = null)    {        return call_user_func($this->getUserResolver(), $guard);    }

Tracking source codeIlluminate\Auth\AuthServiceProviderClass. The Code is as follows:return call_user_func($app['auth']->userResolver(), $guard);

    protected function registerRequestRebindHandler()    {        $this->app->rebinding('request', function ($app, $request) {            $request->setUserResolver(function ($guard = null) use ($app) {                return call_user_func($app['auth']->userResolver(), $guard);            });        });    }

Continue tracing source codeIlluminate\Auth\AuthManagerClass

    public function shouldUse($name)    {        $name = $name ?: $this->getDefaultDriver();        $this->setDefaultDriver($name);        $this->userResolver = function ($name = null) {            return $this->guard($name)->user();        };    }

This is actually the end. We found thatrequest()->user()The final code executed is$this->guard($name)->user(). So we need to checkshouldUserWhere is the method called.

View Source CodeIlluminate\Auth\Middleware\Authenticate:

    protected function authenticate(array $guards)    {        if (empty($guards)) {            return $this->auth->authenticate();        }        foreach ($guards as $guard) {            if ($this->auth->guard($guard)->check()) {                return $this->auth->shouldUse($guard);            }        }        throw new AuthenticationException('Unauthenticated.', $guards);    }

The code is basically clear here, And the authenticated user's request will passAuthenticateMiddleware, and set the system's default guard as the guard of the current request.

// Obtain the authenticated user's guard foreach ($ guards as $ guard) {if ($ this-> auth-> guard ($ guard)-> check ()) {return $ this-> auth-> shouldUse ($ guard );}}

Set the authenticated guard as the default guard instead.config('auth.defaults.guard')Value in

    public function shouldUse($name)    {        $name = $name ?: $this->getDefaultDriver();        $this->setDefaultDriver($name);        $this->userResolver = function ($name = null) {            return $this->guard($name)->user();        };    }
Final Solution

Therefore, the Guard value of the current request can be obtained directly throughAuthManager In classgetDefaultDriver()You can.

 
if ($defaultGuard = $app['auth']->getDefaultDriver()) {   $currentGuard = $defaultGuard;   $user = auth($currentGuard)->user();}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.