laravel-eloquent-filter

nxowjjhe  于 2021-06-25  发布在  Mysql
关注(0)|答案(3)|浏览(389)

我有这两种模式,线索和地位。

class Lead extends Model
{
    public function statuses() {
        return $this->hasMany('App\LeadStatus', 'lead_id', 'id')
            ->orderBy('created_at', 'DESC');
    }

    public function activeStatus() {
        return $this->hasOne('App\LeadStatus', 'lead_id', 'id')
            ->latest();
    }

}

class LeadStatus extends Model
{
    protected $fillable = ['status', 'lead_id'];
}

这个很好用,现在我正在尝试根据最后一个leadstatus的'status'获取所有leads。
我试过几种组合,但都没有成功。

if ($search['status']) {
            $builder = $builder
                ->whereHas('statuses', function($q) use ($search){
                    $q = $q->latest()->limit(1);
                    $q->where('status', $search['status']);
                });
        }

 if ($search['status']) {
            $builder = $builder
                ->whereHas('status', function($q) use ($search){
                    $q = $q->latest()->Where('status', $search['status']);
                });
        }

有人用雄辩的语言做过这件事吗?我需要编写一些原始sql查询吗?
编辑1:我再解释一遍:d
在我的数据库中,潜在客户的状态不是1对1的关系。这是因为我想有一个潜在客户所有状态的历史清单。
这意味着在创建lead时,将创建第一个leadstatus,其状态为“new”,当前日期为。
如果销售人员进来,他可以更改潜在客户的状态,但这不会更新以前的潜在客户状态,而是创建一个新的相关潜在客户状态,当前日期和状态为“未结”。
这样,我可以看到lead是在2018年5月5日创建的,并在2018年5月7日更改为“打开”状态。
现在,我尝试使用elokent编写一个查询,它只统计与潜在客户相关的最新状态。
在上一个示例中,如果我按状态为“new”的lead筛选,则此lead不应出现,因为它现在的状态为“open”。
希望这有帮助

rekjcdws

rekjcdws1#

我也遇到了同样的问题,并在这里发布了我的解决方案,但我认为它值得重新发布,因为它提高了可重用性。这与公认的答案的想法相同,但避免使用联接,如果您想加载关系或在范围中使用联接,则可能会导致问题。
第一步是向查询中添加宏 BuilderAppServiceProvider .

use Illuminate\Database\Query\Builder;

Builder::macro('whereLatestRelation', function ($table, $parentRelatedColumn) 
{
    return $this->where($table . '.id', function ($sub) use ($table, $parentRelatedColumn) {
        $sub->select('id')
            ->from($table . ' AS other')
            ->whereColumn('other.' . $parentRelatedColumn, $table . '.' . $parentRelatedColumn)
            ->latest()
            ->take(1);
    });
});

这基本上使接受答案的子查询部分更通用,允许您指定联接表和它们联接的列。它还使用 latest() 函数以避免引用 created_at 直接列。它假定另一列是“id”列,因此可以进一步改进。要使用它,您可以执行以下操作:

$status = $search['status'];
Lead::whereHas('statuses', function ($q) use ($status) {
    $q->where('status', $userId)
        ->whereLatestRelation((new LeadStatus)->getTable(), 'lead_id');
});

它的逻辑与公认的答案相同,但更容易重用。不过,它会慢一点,但这应该值得重新使用。

zfciruhq

zfciruhq2#

如果我理解正确,您需要/想要获得所有具有特定状态的潜在客户。
所以你应该这样做:

// In your Modal

    public function getLeadById($statusId)
    {
        return Lead::where('status', $statusId)->get();
        // you could of course extend this and do something like this:
        // return Lead::where('status', $statusId)->limit()....->get();
    }

基本上我是在做一个where,然后用一个特定的id返回每个线索。
然后,您可以在控制器中使用此功能,如下所示:

Lead::getLeadById(1)
7dl7o3gd

7dl7o3gd3#

试试这个:

Lead::select('leads.*')
    ->join('lead_statuses', 'leads.id', 'lead_statuses.lead_id')
    ->where('lead_statuses.status', $search['status'])
    ->where('created_at', function($query) {
        $query->selectRaw('max(created_at)')
            ->from('lead_statuses')
            ->whereColumn('lead_id', 'leads.id');
    })->get();

使用主键的解决方案(由borjante提供):

$builder->where('lead_statuses.id', function($query) {
        $query->select('id')
            ->from('lead_statuses')
            ->whereColumn('lead_id', 'leads.id')
            ->orderBy('created_at', 'desc')
            ->limit(1);
    });

相关问题