【问题标题】:Querying related table data with Eloquent使用 Eloquent 查询相关表数据
【发布时间】:2017-05-21 09:52:39
【问题描述】:

我在尝试从基于相关表的模型中获取记录时遇到问题。

我有两张表,一张叫leads,一张叫recycle_logs,我的应用程序基本上会像每月一次一样在leads 表中发送相同的记录,当它发送时我会存储一条新记录在recycle_logs

问题是我需要选择所有具有特定campaign_id 值的leads 并且具有与invalid 不同的特定status,到目前为止一切顺利,现在问题是我需要仅当它们没有与它们关联的任何 recycleLogs 或与特定 lead 关联的最后一个 recycleLog30 天前更早时才获取它们。

我目前拥有的看起来有点像这样。

    $leads = $this->leadModel->where(Lead::CAMPAIGN_ID, $this->campaignID)
                ->where(Lead::DUPLICATED, Lead::DUPLICATED_NO)
                ->where(Lead::LEAD_STATUS, "!=" ,Lead::LEAD_STATUS_INVALID)
                ->orderBy(Lead::CREATED_AT, 'desc')
                ->with(
                    ['leadRecyclingLog' => function($query) {
                        $query->where(LeadRecyclingLog::CREATED_AT, '<', (new Carbon())->subDays($this->configRecyclingDays))
                            ->orWhere(LeadRecyclingLog::ID, null);
                    }]
                )
                ->get();

我到底做错了什么?无论我添加或删除recycleLogs,它总是选择相同数量的记录

我已经设法通过一个原始 SQL 查询来完成它,我将在下面发布它以防它帮助任何人,我仍然想知道如何在 Eloquent/Query Builder 中完成它。

SELECT * FROM `leads` LEFT JOIN `lead_recycling_logs` ON `leads`.`guid` = `lead_recycling_logs`.`original_lead_guid` WHERE `leads`.`campaign_id` = :campaignID AND `leads`.`duplicated` = 0 AND `leads`.`lead_status` != :invalidStatus AND (`lead_recycling_logs`.`id` IS NULL OR `lead_recycling_logs`.`created_at` < :recyclingDate) ORDER BY `leads`.`created_at` DESC

【问题讨论】:

    标签: laravel eloquent query-builder


    【解决方案1】:

    试试这个:

    $leads = $this->leadModel->where(Lead::CAMPAIGN_ID, $this->campaignID)
        ->where(Lead::DUPLICATED, Lead::DUPLICATED_NO)
        ->where(Lead::LEAD_STATUS, "!=" ,Lead::LEAD_STATUS_INVALID)
        ->orderBy(Lead::CREATED_AT, 'desc')
        ->where(function($q) {
            $q->whereHas('leadRecyclingLog', function($q) {
                $q->where(LeadRecyclingLog::CREATED_AT, '<', (new Carbon())->subDays($this->configRecyclingDays));
            })
            ->orWhereHas('leadRecyclingLog', '<', 1); // Where count of the relationship is smaller than 1
        })->get();
    

    我假设查询的第一部分运行良好(直到关系)。

    您要查找的是-&gt;whereHas(relationship),而不是-&gt;with(relationship)-&gt;with(relationship) 会将关联的结果附加到原始模型中(原始模型的查询不受-&gt;with() 的影响)。 -&gt;whereHas(relationship) 按条件过滤原始模型。

    【讨论】:

    • orWhereDoesntHave 不是查询生成器的方法,因此这也不起作用。我已经设法在一个简单的 MySQL 原始查询中复制了我想要的东西,它工作得很好,如果有帮助,我会将它添加到问题中。
    • orWhereHas 的第二个参数必须是闭包
    • 通过稍微修改您的查询使其工作,感谢您的帮助:)
    【解决方案2】:

    通过@devk 的帮助让它工作

        $leads = $this->leadModel->where(Lead::CAMPAIGN_ID, $this->campaignID)
            ->where(Lead::DUPLICATED, Lead::DUPLICATED_NO)
            ->where(Lead::LEAD_STATUS, "!=" ,Lead::LEAD_STATUS_INVALID)
            ->orderBy(Lead::CREATED_AT, 'desc')
            ->where(function($q) {
                $q->whereHas('leadRecyclingLog', function($q) {
                    $q->where(LeadRecyclingLog::CREATED_AT, '<', (new Carbon())->subDays($this->configRecyclingDays));
                })
                    ->doesntHave('leadRecyclingLog', 'or');
            })->get();
    

    【讨论】:

      猜你喜欢
      • 2021-03-21
      • 2013-05-25
      • 2015-09-30
      • 2018-12-08
      • 1970-01-01
      • 2021-09-25
      • 2016-05-25
      • 2018-11-11
      • 2015-06-24
      相关资源
      最近更新 更多