You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel多表关联查询后如何合并重复客户记录展示?

解决方案:合并同一客户的联系方式记录

当然可以实现,下面提供两种常用的解决思路:

方法一:使用查询构造器结合聚合函数(适合直接用DB类的场景)

利用数据库的聚合函数(如MySQL的GROUP_CONCAT)将同一客户的多条电话、邮箱合并为字符串,同时通过GROUP BY按客户分组,避免重复记录。另外需要修正原代码中OR条件的逻辑问题(原写法会导致搜索条件脱离主表关联,引发错误)。

修改后的代码如下:

public function customersList(Request $request)
{
    $query = DB::table('customers')
        ->leftJoin('phones', 'customers.id', '=', 'phones.customer_id')
        ->leftJoin('emails', 'customers.id', '=', 'emails.customer_id')
        ->select(
            'customers.id',
            'customers.name',
            DB::raw('GROUP_CONCAT(DISTINCT phones.phone SEPARATOR ", ") as phones'),
            DB::raw('GROUP_CONCAT(DISTINCT emails.email SEPARATOR ", ") as emails')
        )
        ->groupBy('customers.id', 'customers.name');

    if (!empty($request->value)) {
        $searchValue = '%' . $request->value . '%';
        $query->where(function ($q) use ($searchValue) {
            $q->where('customers.name', 'like', $searchValue)
              ->orWhere('emails.email', 'like', $searchValue)
              ->orWhere('phones.phone', 'like', $searchValue);
        });
    }

    $info = $query->get();
    // 可选:将逗号分隔的字符串转成数组,方便前端处理
    // $info = $info->map(function($item) {
    //     $item->phones = explode(', ', $item->phones) ?: [];
    //     $item->emails = explode(', ', $item->emails) ?: [];
    //     return $item;
    // });
    return $info;
}

说明:

  • 改用leftJoin确保即使客户没有电话或邮箱也能被查询到
  • GROUP_CONCAT的DISTINCT参数避免重复的联系方式
  • 搜索条件用闭包包裹,保证OR逻辑只作用于搜索字段,不破坏表关联的条件

方法二:使用Eloquent关联(更符合Laravel的ORM设计)

如果已经定义了Eloquent模型,这种方式更优雅,通过定义一对多关联,然后在查询时预加载关联数据,最后通过集合处理合并:

  1. 先定义模型关联:
// Customer.php 模型
class Customer extends Model
{
    public function phones()
    {
        return $this->hasMany(Phone::class);
    }

    public function emails()
    {
        return $this->hasMany(Email::class);
    }
}
  1. 修改控制器方法:
public function customersList(Request $request)
{
    $query = Customer::with(['phones', 'emails']);

    if (!empty($request->value)) {
        $searchValue = '%' . $request->value . '%';
        $query->where(function ($q) use ($searchValue) {
            $q->where('name', 'like', $searchValue)
              ->orWhereHas('phones', function ($q2) use ($searchValue) {
                  $q2->where('phone', 'like', $searchValue);
              })
              ->orWhereHas('emails', function ($q2) use ($searchValue) {
                  $q2->where('email', 'like', $searchValue);
              });
        });
    }

    $info = $query->get()->map(function($customer) {
        return [
            'id' => $customer->id,
            'name' => $customer->name,
            'phones' => $customer->phones->pluck('phone')->toArray(),
            'emails' => $customer->emails->pluck('email')->toArray(),
        ];
    });

    return $info;
}

说明:

  • with(['phones', 'emails'])预加载关联数据,避免N+1查询问题
  • whereHas用于搜索关联表中的字段
  • 通过集合的map和pluck方法,将关联的电话、邮箱整理成数组,合并到客户记录中

内容的提问来源于stack exchange,提问作者Solutions

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 20:35:24