【问题标题】:Laravel: How to get data from 3 tables with relationshipLaravel:如何从具有关系的 3 个表中获取数据
【发布时间】:2020-01-06 11:04:26
【问题描述】:

我有 3 张桌子:

Customers

  • 身份证
  • 姓名

Sales

  • customer_id
  • 销售日期

Contacts

  • customer_id
  • 联系日期

contacts 表中没有任何更新操作。每个进程在contacts 表中打开一条新记录。因此,一个用户在contacts 表中可以有多个记录。

这是我在模型中的关系:

Customer

public function contacts()
{
    return $this->hasMany(Contact::class);
}

public function sales()
{
    return $this->hasMany(Sale::class);
}

Contact

public function customer()
{
    return $this->belongsTo('App\Customer', 'customer_id');
}

Sale

public function customer()
{
    return $this->belongsTo('App\Customer');
}

我想获得contacts 表的最新记录,并使其与其他相关表连接。

这是我尝试过的查询:

$record = Contact::groupBy('customer_id')
        ->select(DB::raw('max(id)'));

$result = Customer::query();
$result->where('is_active', 'YES');
$result->with('sales');
$result->whereHas('contacts', function ($q) use($record){
        return $q->whereIn('id', $record)->where('result', 'UNCALLED');
    });
return $result->get();

在刀片文件中,我在foreach 循环中得到了一些结果。但是,我无法从salescontacts 表中获取相关数据。

@foreach($result as $item)
@foreach($item->sales as $sale) // Has no output and gives error: Invalid argument supplied for foreach() 
@foreach($item->contacts as $contact) // Has no output and gives error: Invalid argument supplied for foreach()

谁能帮助我如何显示销售和联系日期?或者对如何提高此代码质量有任何想法?

【问题讨论】:

  • 你有没有在你的 eloquent 模型中尝试过 protected $with 属性?
  • 快速笔记;关系名称应反映返回的结果数量。你有contactsale,它们都使用hasMany() 并且返回不止一个,所以它们真的应该是contactssales 以避免混淆。 customer 很好,因为 belongsTo() 固有地返回一条记录。
  • @TimLewis 是的,你是对的。抱歉拼错了。我更正了。
  • 别担心!只要确保也修复参考; $item->sales 而不是 $item->sale$item->contacts 而不是 $item->contact
  • @MadameGreenPea 你如何将结果发送到视图?

标签: laravel eloquent eloquent-relationship


【解决方案1】:

如果您想要联系人的最新记录,您可以在Customer 模型上声明另一个关系,例如:

public function latest_contact()
{
    return $this->hasOne(Contact::class)->latest('contact_date');
}

顺便说一句,如果你有一个hasMany,你总是可以声明一个或多个hasOne附加关系,外键使用是相同的。

通过这种方式,您可以使用您的Customer 模型检索latest_contact 渴望加载

$customer = Customer::with('latest_contact')->find($id);

或者在您的查询中使用这种关系,例如:

$customers = Customer::where('is_active', 'YES')
    ->with('sales')
    ->with('contacts')
    ->whereHas('last_contact', function ($q){
        return $q->where('result', 'UNCALLED');
    })->get();

或者说:

$customers = Customer::where('is_active', 'YES')
    ->with('sales')
    ->with('contacts')
    ->with('last_contact', function ($q){
        return $q->where('result', 'UNCALLED');
    })->get();

如果您愿意,可以声明 last_contact 和附加的 where

public function latest_contact()
{
    return $this->hasOne(Contact::class)
        ->where('result', 'UNCALLED')
        ->latest('contact_date');
}

这样所有其他查询应该更容易。 我希望这可以帮助你。

【讨论】:

  • 谢谢。但是,我仍然无法在视图文件中获得销售日期和联系日期。所以,不幸的是,结果是一样的。我不明白为什么。
  • 这个想法很简单:通过hasMany 关系,您可以在具有附加条件的同一模型上声明其他hasOnehasMany,尝试使用该想法和您的数据,您的查询应该更容易。
【解决方案2】:

我不确定,但您可以尝试执行以下操作吗:

return Customer::where('is_active', 'YES')
    ->with([
        'sale', 
        'contact' => function ($query) use($record) {
            return $query->whereIn('id', $record)->where('result', 'UNCALLED');
        }
    ])->get();

【讨论】:

  • 这将返回所有活动的Customer 记录,但最初的问题是使用->whereHas() 添加额外的过滤,所以这是一种不正确的方法。你导致->with()->whereHas()同时使用来限制->contact的返回结果,但是省略它是错误的。
猜你喜欢
  • 2019-01-06
  • 1970-01-01
  • 2018-07-08
  • 1970-01-01
  • 2021-07-27
  • 1970-01-01
  • 2021-08-06
  • 2017-10-26
  • 2014-09-16
相关资源
最近更新 更多