如图,一个服务(service)对应一个用户(user),一个用户对应多个标签(tag),同时一个tag也可以通过中间表(pivot)对应对个用户。

现在业务需求如下:查service,这些service对应的user同时拥有tag1、tag2、tag3、tag4标签。

一个很容易犯的错误如下:

$tags = ['tag1', 'tag2', 'tag3', ''tag4];

$query = ServiceModel::query()

$query->whereHas('user.tags', function($query) use($tags) {
foreach($tags as $tag){
$query->where('tag_name', '=', $tag);
}
}); $query-get();

这翻译过来是:找到某service,该service有user,且user有tag,这些tag的tag_name还要满足既等于tag1又等于tag2又等于tag3还等于tag4。

很显然,查询的结果为空,因为一个tag只有一个tag_name。

那换种方式:

$tags = ['tag1', 'tag2', 'tag3', ''tag4];

$query = ServiceModel::query()

$query->whereHas('user.tags', function($query) use($tags) {
$query->whereIn('tag_name', $tags);
}); $query-get();

这样也不对,因为要同时拥有4种标签,这种写法标签间是OR的关系

翻译过来是:找到某service,该service有user,且user有tag,这些tag的tag_name只要出现在tag1、tag2、tag3、tag4中就选出来。

那如何找到某service,该service对应的user的标签既有tag1又有tag2又有tag3还有tag4呢?

其实只要把foreach置于外部即可:

$tags = ['tag1', 'tag2', 'tag3', ''tag4];

$query = ServiceModel::query()

foreach($tags as $tag){
$query->whereHas('user.tags', function($query) use($tag) {
$query->where('tag_name', '=', $tag);
});
} $query-get();

这样翻译过来:(第一个循环)找到某service,该service有user,且user有tag,tag为tag1 ;循环加入的条件都是AND的关系。

其实还是化繁为简的思想:

找到某service,其对应user同时拥有多个tag的查询太难了,挺绕,那先找到只拥有1个tag(如tag1)的全部service记录总可以吧:

$query = ServiceModel::query()

$query->whereHas('user.tags', function($query) use($tag) {
$query->where('tag_name', '=', 'tag1');
});

这和laravel手册上基于存在的关联查询例子几乎一样,那找到只拥有tag2的service记录,不就是把where里面的tag1换成tag2吗,同理其他tag,那这不就相当于对tag数组循环并添加whereHas条件吗...

最新文章

  1. CHARINDEX
  2. 永远不要修改arguments对象
  3. webbench详解
  4. Raspberry Pi 3 --- Kernel Building and Run in A New Version Kernal
  5. svn server
  6. EF Power Tools
  7. 注解框架ButterKnife
  8. pycharm的使用技巧
  9. MySQL 架构
  10. Oracle免费的便捷Web应用开发框架
  11. 银河麒麟操作系统打开VMware报vmmon无法编译
  12. linux操作系统基础篇(六)
  13. hiho-1015- KMP算法
  14. URL编码和Base64编码 (转)
  15. Chrome 内存和CPU消耗量双料冠军
  16. 记录日常Linux常用软件
  17. mysql杯观锁与乐观锁
  18. comfirm和prompt的区别
  19. VS2015 之 多行缩进
  20. 【转载】JSP生成静态Html页面

热门文章

  1. sed命令讲解
  2. 20175202 《Java程序设计》第六周学习总结
  3. 导入tensorflow时DLL load failed: 找不到指定的模块
  4. MariaDB的安装与启动
  5. E4A 与JS交互事件无反应
  6. 用openssl为EAP-TLS生成证书(CA证书,服务器证书,用户证书)
  7. windows使用im4java 提示FileNotFoundException
  8. Halcon Visinpro 破解版
  9. spark2.1源码分析1:Win10下IDEA源码阅读环境的搭建
  10. bootstrap的使用集锦