tp5 多对多关联with 子查询
时间: 2024-12-31 15:42:23 浏览: 55
### ThinkPHP5 中多对多关联查询使用 `with` 方法结合子查询
在 ThinkPHP5 中处理复杂的多对多关系时,可以利用 `with()` 方法来优化性能并简化代码逻辑。对于涉及子查询的情况,可以通过定义合适的模型关联以及构建合理的查询语句来实现。
#### 定义多对多关联
假设存在两个实体:`ContactModel`(联系人) 和 `EnterpriseModel`(企业),二者之间通过中间表 `relation_table` 建立了多态或多对多的关系。为了仅获取特定类型的关联记录(比如这里是指定 type=3 的企业),可以在 ContactModel 类中定义如下方法:
```php
public function enterprises()
{
return $this->belongsToMany(
'app\model\EnterpriseModel',
'relation_table', // 中间表名称
'contact_id', // 当前模型外键名
'enterprise_id' // 关联模型外键名
)->where('type', '=', 3); // 添加额外的筛选条件
}
```
此部分配置确保当调用该关联时自动应用指定的过滤规则[^1]。
#### 使用 `with` 进行预加载
为了让查询更加高效,应该尽可能减少数据库交互次数。因此,在实际项目开发过程中推荐采用 `with()` 来一次性抓取所需数据而不是单独请求每一个对象的数据集。例如要获得某个联系人的所有符合条件的企业列表,则可这样操作:
```php
$contacts = \app\model\ContactModel::with(['enterprises'])->select();
foreach ($contacts as $contact){
echo "Contact ID:".$contact['id']." has these enterprises:\n";
foreach($contact->enterprises as $enterprise){
echo "- Enterprise Name: ".$enterprise['name']."\n";
}
}
```
这段代码展示了如何先从 `ContactModel` 表里选出所有的联系人,并且预先加载他们各自对应的经过筛选后的合作企业信息。注意这里的 `'enterprises'` 是之前自定义的方法名字[^2]。
#### 结合子查询进一步定制化需求
如果还需要基于某些动态参数或者其他复杂业务场景来进行更深层次的数据挖掘,那么就可以考虑引入子查询的概念。具体来说就是在原有基础上增加一层嵌套式的 SQL 查询表达式作为附加条件之一。举个例子,如果我们想要找出那些在过去一年内有过交易活动的合作企业的话,可能会这样做:
```php
use think\Db;
// 构建时间范围内的订单统计子查询
$subQuery = Db::table('orders')
->field('COUNT(*) AS order_count, enterprise_id')
->whereTime('created_at', 'yesterday.year')
->group('enterprise_id');
// 将其应用于主查询之中
$contacts = \app\model\ContactModel::with([
'enterprises'=>function($query) use ($subQuery){
$query->leftJoin("( {$subQuery} ) orders", 'enterprises.id','=','orders.enterprise_id');
->havingRaw('order_count > ?', [0]);
}])
->select();
foreach ($contacts as $contact){
...
}
```
上述片段说明了怎样把一个计算最近一年订单数量的小查询融入到主要的选择流程当中去,从而达到精准定位活跃企业的目的。当然这只是一个简单的示意,实际情况可能更为复杂一些[^3]。
阅读全文
相关推荐




















