摘要:因為客戶希望能夠直觀的看到目前購物車中商品信息,以便推送優(yōu)惠信息來促使轉(zhuǎn)化。用戶在商城中的購物車數(shù)據(jù)導(dǎo)購使用導(dǎo)購小程序代用戶下單或結(jié)賬時加入的購物車數(shù)據(jù),不和用戶購物車數(shù)據(jù)同步。
iBrand 產(chǎn)品中關(guān)于購物車的需求比較復(fù)雜,我們基于 overture/laravel-shopping-cart 擴(kuò)展出了更加符合電商需求的購物車包,之前有文章進(jìn)行過簡單的介紹: Laravel shopping cart : 電商購物車包,線上完美運行中
源碼地址: ibrand/laravel-shopping-cart原需求
最開始擴(kuò)展這個包時是因為以下需求:
用戶登錄后的購物車數(shù)據(jù)需要存儲在數(shù)據(jù)庫中。因為客戶希望能夠直觀的看到目前購物車中商品信息,以便推送優(yōu)惠信息來促使轉(zhuǎn)化。雖然我們按照 GA 的標(biāo)準(zhǔn)把數(shù)據(jù)傳送過去了,但是我們發(fā)現(xiàn) GA中數(shù)據(jù)并不是非常準(zhǔn)確。
用戶在商城中的購物車數(shù)據(jù)
導(dǎo)購使用導(dǎo)購小程序代用戶下單或結(jié)賬時加入的購物車數(shù)據(jù),不和用戶購物車數(shù)據(jù)同步。
原解決方案最初需求出來的時候,我們通過不同的 Guard 來作為用戶購物車數(shù)據(jù)的區(qū)分,因為商城和導(dǎo)購是兩種不同的用戶系統(tǒng),所以當(dāng)時在購物車 ServiceProvider 中的代碼如下:
$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."); }
通過循環(huán)遍歷目前所有的 Guards 來獲取目前請求中用戶所屬的 guard 值和用戶對象,本來在新需求未增加時,一切都運行的挺正常。
新需求18年新增的需求:
用戶門店掃碼(二維碼或條形碼)自助下單的購物車數(shù)據(jù)要和商城的購物車數(shù)據(jù)區(qū)分
也就是現(xiàn)在存在三種購物車數(shù)據(jù)類型
用戶在商城的購物車數(shù)據(jù)
用戶在線下門店中自助下單的購物車數(shù)據(jù)
導(dǎo)購的購物車數(shù)據(jù)
新需求解決方案新需求出現(xiàn)的時候,為了區(qū)分購物車數(shù)據(jù),肯定是直接新建一個 guard,所以在 config/auth.php 中添加了 shop guard 代碼如下。
"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", ], ],問題產(chǎn)生
本以為會運行良好,但是我們忽略了一個細(xì)節(jié),api 和 shop 兩個 guard 的 provider 是一樣的,因為都是屬于用戶的,而 api 又定義在 shop 前面,所以當(dāng)執(zhí)行如下代碼時會出現(xiàn)問題,因為循環(huán)到 auth("api")->user() 的時候就退出了,導(dǎo)致了 shop guard 的數(shù)據(jù)也會存儲成 api guard.
foreach ($guards as $guard) { if ($user = auth($guard)->user()) { $currentGuard = $guard; break; } }解決方案
之前工程師未發(fā)現(xiàn)合適的方法,所以采用了循環(huán)遍歷 guards 來判斷當(dāng)前請求已認(rèn)證 guard,當(dāng)新需求產(chǎn)生后,這個方法不再適用,但是又不能對當(dāng)前的購物車包進(jìn)行大改,所以只有再找解決辦法,
思路在 Laravel 中 request()->user() 都會獲取到正確已認(rèn)證的 guard user 數(shù)據(jù),所以準(zhǔn)備決定從這里的源碼入手。
源碼分析request()->user() 實際調(diào)用的代碼是 IlluminateHttpRequest class 中 user() 方法
public function user($guard = null) { return call_user_func($this->getUserResolver(), $guard); }
追蹤源碼到 IlluminateAuthAuthServiceProvider class,具體執(zhí)行的代碼為: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); }); }); }
繼續(xù)追蹤源碼到 IlluminateAuthAuthManager class
public function shouldUse($name) { $name = $name ?: $this->getDefaultDriver(); $this->setDefaultDriver($name); $this->userResolver = function ($name = null) { return $this->guard($name)->user(); }; }
到這里其實就結(jié)束了,我們發(fā)現(xiàn) request()->user() 最終執(zhí)行的代碼是 $this->guard($name)->user() 。所以我們需要查看下 shouldUser 方法是在哪里調(diào)用的。
仍然看源碼 IlluminateAuthMiddlewareAuthenticate:
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); }
代碼最終到這里基本比較清楚了,已認(rèn)證用戶的請求會通過 Authenticate middleware ,并且把系統(tǒng)默認(rèn)的 guard 設(shè)置為當(dāng)前請求的 guard.
//獲取到已認(rèn)證用戶的 guard foreach ($guards as $guard) { if ($this->auth->guard($guard)->check()) { return $this->auth->shouldUse($guard); } }
設(shè)置已認(rèn)證 guard 為默認(rèn) guard,代替 config("auth.defaults.guard") 中的值
public function shouldUse($name) { $name = $name ?: $this->getDefaultDriver(); $this->setDefaultDriver($name); $this->userResolver = function ($name = null) { return $this->guard($name)->user(); }; }最終方案
所以獲取到當(dāng)前請求的 Guard 值,可以直接通過 AuthManager class 中的 getDefaultDriver() 即可。
if ($defaultGuard = $app["auth"]->getDefaultDriver()) { $currentGuard = $defaultGuard; $user = auth($currentGuard)->user(); }討論交流
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/28477.html
摘要:購物車在電商場景中基本是必須的一個模塊,我們基于進(jìn)行擴(kuò)展開發(fā)。主要實現(xiàn)了以下擴(kuò)展購物車數(shù)據(jù)支持存儲增加屬性返回。因為購物車可能是或者,因此直接通過屬性直接返回相關(guān)對象。支持多因為在產(chǎn)品有商城購物車和導(dǎo)購購物車。 我們秉承得益開源社區(qū),也奉獻(xiàn)開源社區(qū)的原則,我們會陸續(xù)將正在線上使用的穩(wěn)定包提交到 github 上,同時在后續(xù)的開源產(chǎn)品中,也會用到,大家可以放心使用。 購物車在電商場景中基...
摘要:最佳實踐良好的編碼規(guī)范單元測試持續(xù)集成文檔,從一開始就形成良好的編碼習(xí)慣。真實的電商業(yè)務(wù)所有的業(yè)務(wù)需求來自真實的客戶,并且線上良好運營中。 重要通知: Laravel + 小程序的開源電商版本源碼已經(jīng)在 github 上拉,歡迎提交 issue 和 star :) 開源電商 Server 端: Laravel API源碼 開源電商 client 端:小程序源碼 iBrand 簡介...
摘要:社交新零售電商產(chǎn)品從年月啟動至今,已經(jīng)趨于穩(wěn)定,而且已經(jīng)初步得到市場的檢驗,特別能抗住電商中秒殺時高并發(fā)的交易場景。產(chǎn)品包含微商城,小程序,導(dǎo)購小程序端,因此是前后端完全分離的,在這種情況下,沒有一個跟蹤分析執(zhí)行效率的工具。 iBrand 社交新零售電商產(chǎn)品從2016年9月啟動至今,已經(jīng)趨于穩(wěn)定,而且已經(jīng)初步得到市場的檢驗,特別能抗住電商中秒殺時高并發(fā)的交易場景。 接下來我們團(tuán)隊會逐步...
摘要:通過裝載看守器和用戶提供器裝載看守器和用戶提供器用到的方法比較多,用文字描述不太清楚,我們通過注解這個過程中用到的方法來看具體的實現(xiàn)細(xì)節(jié)。 用戶認(rèn)證系統(tǒng)的實現(xiàn)細(xì)節(jié) 上一節(jié)我們介紹來Laravel Auth系統(tǒng)的基礎(chǔ)知識,說了他的核心組件都有哪些構(gòu)成,這一節(jié)我們會專注Laravel Auth系統(tǒng)的實現(xiàn)細(xì)節(jié),主要關(guān)注Auth也就是AuthManager是如何裝載認(rèn)證用的看守器(Guard)...
摘要:本文由網(wǎng)易跨境電商部產(chǎn)品經(jīng)理曹宏授權(quán)發(fā)表。根據(jù)交易鏈路的環(huán)節(jié),分工可以進(jìn)一步簡單細(xì)化為商詳頁產(chǎn)品導(dǎo)購頁產(chǎn)品,購物車產(chǎn)品,訂單產(chǎn)品,支付產(chǎn)品。那么購物車的產(chǎn)品都在做什么為了避免假大空,就以購物車改版這個項目介紹一下電商購物車產(chǎn)品的工作。 本文由網(wǎng)易跨境電商部產(chǎn)品經(jīng)理曹宏授權(quán)發(fā)表。 作為電商交易鏈路的產(chǎn)品,很多人會問,你們都在做什么? 關(guān)于電商產(chǎn)品的工作分類,從流量角度我簡單分為以下幾類(...
閱讀 1129·2021-10-14 09:43
閱讀 1185·2021-10-11 11:07
閱讀 3133·2021-08-18 10:23
閱讀 1516·2019-08-29 16:18
閱讀 1032·2019-08-28 18:21
閱讀 1501·2019-08-26 12:12
閱讀 3789·2019-08-26 10:11
閱讀 2534·2019-08-23 18:04