Eloquent加密字段查询异常:无法获取全部符合条件的发票数据
看起来你的查询逻辑出了问题,主要是运算符优先级导致条件判断混乱,另外还要注意加密字段的查询方式是否正确。咱们一步步来解决:
1. 修复查询逻辑错误
你的原查询中,whereHas、where和orWhere的组合方式不对,因为AND的优先级比OR高,导致最终的查询逻辑变成了:
(匹配指定nif的客户 AND 状态为0) OR 匹配指定nif的客户 OR 状态为2
这会导致所有状态为2的发票都被拉出来,不管是否属于目标客户,同时重复的whereHas也完全没必要。
正确的逻辑应该是:匹配指定nif的客户,并且发票状态是0或者2,你可以用以下两种方式实现:
方法一:用闭包分组状态条件
$nif = \Crypt::decryptString(\Auth::user()->userprofile->nif_dni_cif); $invoices = Invoices::whereHas('userclient', function($query) use($nif) { $query->where('nif', $nif); }) ->where(function($query) { $query->where('status', 0) ->orWhere('status', 2); }) ->orderBy('updated_at', 'desc') ->get();
方法二:用whereIn简化状态判断(更简洁)
$nif = \Crypt::decryptString(\Auth::user()->userprofile->nif_dni_cif); $invoices = Invoices::whereHas('userclient', function($query) use($nif) { $query->where('nif', $nif); }) ->whereIn('status', [0, 2]) ->orderBy('updated_at', 'desc') ->get();
2. 检查加密字段的查询方式
你提到“身份文档字段为加密存储”,如果这里指的是数据库中userclient表的nif字段是加密存储的,那原查询的匹配方式就错了:
- 你现在是把当前用户的加密nif解密成明文,然后用明文去匹配数据库里的加密字段,这肯定匹配不到(除非数据库里的nif是明文)。
正确的做法应该是:把明文的$nif加密后,再去匹配数据库里的加密字段,也就是修改whereHas里的条件:
$nif = \Crypt::decryptString(\Auth::user()->userprofile->nif_dni_cif); // 把明文nif加密,匹配数据库里的加密字段 $encryptedNif = \Crypt::encryptString($nif); $invoices = Invoices::whereHas('userclient', function($query) use($encryptedNif) { $query->where('nif', $encryptedNif); }) ->whereIn('status', [0, 2]) ->orderBy('updated_at', 'desc') ->get();
如果userclient的nif是明文存储的,那这一步可以忽略,只需要修复查询逻辑即可。
额外提示
如果同一客户有多条userclient记录,whereHas会自动匹配所有关联的记录,只要有一条符合条件就会返回对应的发票,所以不需要额外处理多记录的情况。
内容的提问来源于stack exchange,提问作者jagcweb
相关产品推荐
相关产品推荐

