记一次laravel远程关联查询

如图,一个服务(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条件吗...
记一次laravel远程关联查询的更多相关文章
- Laravel 在 with 查询中只查询个别字段
在使用 Laravel 的关联查询中,我们经常使用 with 方法来避免 N+1 查询,但是 with 会将目标关联的所有字段全部查询出来,对于有强迫症的我们来说,当然是不允许的. 这时候我们可以使用 ...
- laravel 中with关联查询限定查询字段
学习了下laravel5.6框架,果然很优雅,比如ActiveJieSuan model中作如下关联:(laravel模型关联关系可以查看https://laravelacademy.org/post ...
- 完爆Facebook/GraphQL,APIJSON全方位对比解析(三)-表关联查询
相关阅读: 完爆Facebook/GraphQL,APIJSON全方位对比解析(一)-基础功能 完爆Facebook/GraphQL,APIJSON全方位对比解析(二)-权限控制 自APIJSON发布 ...
- JAVA-Unit03: SQL(基础查询) 、 SQL(关联查询)
Unit03: SQL(基础查询) . SQL(关联查询) 列别名 当SELECT子句中查询的列是一个函数 或者表达式时,那么查询出来的结果集 中对应的该字段的名字就是这个函数或者 表达式的名字.为此 ...
- JDBC MySQL 多表关联查询查询
public static void main(String[] args) throws Exception{ Class.forName("com.mysql.jdbc.Driver&q ...
- MYSQL基础操作之数据约束与关联查询
一.MYSQL约束 1.默认值约束,当字段没有插入值的时候,mysql自动给该字段分配默认值. 默认值的字段允许为空. 对默认值字段也可以插入null. CREATE TABLE STUDENT( I ...
- C#代码中实现两个表(DataTable)的关联查询(JOIN)
之前通常都是使用SQL直接从数据库中取出表1和表2关联查询后的数据,只需要用一个JOIN就可以了,非常方便.近日遇到一种情况,两个表中的数据已经取到代码中,需要在代码中将这两个表关联起来,并得到它们横 ...
- Mybatis关联查询和数据库不一致问题分析与解决
Mybatis关联查询和数据库不一致问题分析与解决 本文的前提是,确定sql语句没有问题,确定在数据库中使用sql和项目中结果不一致. 在使用SpringMVC+Mybatis做多表关联时候,发现也不 ...
- Mysql多表表关联查询 inner Join left join right join
Mysql多表表关联查询 inner Join left join right join
随机推荐
- CRM-stark组件
stark组件 1. stark也是一个app(用startapp stark创建),目标时把这个做成一个可以拔插的组件 2. setting文件下INSTALLED_APPS 路径要配置好(app的 ...
- 20175202 《Java程序设计》第六周学习总结
20175202 2018-2019-2 <Java程序设计>第六周学习总结 教材知识点总结 1.内部类: Java支持在一个类中定义另一个类,称作内部类,包含内部类的类叫做外嵌类. 内部 ...
- Btrace 拦截构造函数,同名函数
拦截方法: 1.普通方法 @OnMethod(clazz="", method="") 2.构造函数@OnMethod(claszz="" ...
- HanLP中文分词Lucene插件
基于HanLP,支持包括Solr(7.x)在内的任何基于Lucene(7.x)的系统. Maven <dependency> <groupId>com.hankcs.nlp&l ...
- C编程中printf不加'\n'不输出
有时,使用printf("a=%d",a);并不一定会输出显示,只有当在格式化输出时加上'\n'才能输出,如printf("a=%d\n",a); 由于unix ...
- Linux下mysql的root密码修改方法(ERROR 1054)
#1.停止mysql数据库 /etc/init.d/mysqld stop #2.执行如下命令 mysqld_safe --user=mysql --skip-grant-tables --skip- ...
- PhpStorm 2018 破解方法
破解方法如下: 1.修改phpstrom的验证服务器地址. 在C:\Windows\System32\drivers\etc目录下打开hosts文件,并在文件最后加入 0.0.0.0 account. ...
- python用字符串调用当前模块内的函数
eval(字符串)() vars()[字符串]() 例如:
- 联想T470笔记本GPT改MBR分区
联想T470笔记本GPT改MBR分区 7000多元买的,这个笔记本配置还可以,就是感觉特别卡顿,于是想重做WIN7系统,为了方便激活,想把GPT分区改成MBR分区. 进入微PE1.2,用傲梅分区助手删 ...
- Linux文件与目录管理(学习笔记)
本笔记为<鸟哥linux私房菜>第六章学习笔记 一.目录与路径 相对路径与绝对路径 绝对路径:一定由根目录 / 写起 正确度比较好 相对路径:不是由 / 写起 ...