使用Cookie Token获取数据库搜索历史为空问题排查与解决
我尝试通过已保存的Cookie Token从数据库获取搜索历史数据,但始终无法获取有效内容,history数组一直为空,请求协助解决。
相关代码片段
控制器get方法
public function get() { $cookieToken = Cookie::get('search_token'); $userId = Auth::id(); $history = $this->getSearchHistory($cookieToken, $userId); $popular = $this->getPopularSearches(); return response()->json([ 'status' => 'success', 'message' => 'Search History', 'data' => [ 'history' => $this->transformSearchHistory($history), 'popular' => $this->transformPopularSearches($popular) ] ]); }
获取搜索历史方法
protected function getSearchHistory($cookieToken, $userId) { return SearchHistory::select('search_term', DB::raw('MAX(id) as id'), DB::raw('MAX(cookie_token) as cookie_token'), DB::raw('MAX(user_id) as user_id')) ->where(function ($query) use ($cookieToken, $userId) { if (!empty($userId)) { $query->where('user_id', $userId); } elseif (!empty($cookieToken)) { $query->where('cookie_token', $cookieToken); } }) ->groupBy('search_term') ->orderBy('id', 'desc') ->limit(6) ->get(); }
转换搜索历史数据方法
protected function transformSearchHistory($history) { return $history->map(function ($item) { return [ 'id' => $item->id, 'search_term' => $item->search_term, 'cookie_token' => $item->cookie_token, ]; })->toArray(); }
期望返回结果
{ "status": "success", "message": "Search History", "data": { "history": [ {"id": 4, "search_term": "Apple", "cookie_token": "RHyIYWSXsgBtKPj7RuPG0jNM5m9mnRZO"}, {"id": 2, "search_term": "Samsung", "cookie_token": "ZFqKwNJA6AKLaorkcODALjgJBPPcywU7"}, {"id": 1, "search_term": "Beko", "cookie_token": "ZFqKwNJA6AKLaorkcODALjgJBPPcywU7"} ], "popular": [ {"id": 1, "search_term": "Apple", "count": 24}, {"id": 2, "search_term": "Samsung", "count": 12}, {"id": 6, "search_term": "Beko", "count": 5}, {"id": 7, "search_term": "iphone", "count": 3} ] } }
排查与解决方案
1. 验证Cookie Token的正确性
- 在
get()方法中添加dd($cookieToken);,确认后端是否正确获取到search_token的值。 - 检查前端请求是否携带该Cookie,注意Cookie的域名、路径、HttpOnly属性是否与后端配置匹配,避免Cookie无法传递到后端。
2. 修正查询逻辑的缺陷
原查询使用MAX(cookie_token)和MAX(user_id)存在逻辑漏洞:当同一个search_term对应不同cookie_token的记录时,MAX(cookie_token)可能返回非当前查询的Token值,导致数据不匹配。建议改用子查询获取每个搜索词的最新记录:
protected function getSearchHistory($cookieToken, $userId) { // 先获取每个search_term对应的最新记录ID $latestIds = SearchHistory::select('search_term', DB::raw('MAX(id) as max_id')) ->where(function ($query) use ($cookieToken, $userId) { if ($userId) { $query->where('user_id', $userId); } elseif ($cookieToken) { $query->where('cookie_token', $cookieToken); } }) ->groupBy('search_term'); // 关联原表获取完整的最新记录 return SearchHistory::select('id', 'search_term', 'cookie_token') ->joinSub($latestIds, 'latest_records', function ($join) { $join->on('search_history.id', '=', 'latest_records.max_id'); }) ->orderBy('id', 'desc') ->limit(6) ->get(); }
3. 检查数据库数据
- 确认
search_history表中存在对应cookie_token的记录,且search_term、cookie_token字段值无大小写、空格等格式问题。 - 验证查询优先级:如果用户已登录(
$userId不为空),查询会优先使用user_id,此时需确认该用户ID下是否有历史记录;若未登录,才会使用cookie_token查询。
4. 调试查询语句
在getSearchHistory()方法中添加dd($query->toSql(), $query->getBindings());,查看最终生成的SQL语句和绑定参数,直接在数据库客户端执行,确认是否能返回预期数据。
内容的提问来源于stack exchange,提问作者Samet Göktepe
相关产品推荐
相关产品推荐

