Eloquent 按关系筛选(仅最后一条记录)

Eloquent Filter by relationship (ONLY last record)

我将我的问题编辑得更明确

我需要构建一个范围来过滤 hasMany 关系。问题是,我想将该查询应用于 lastONLY,我的意思是,我希望我的模型按特定记录的列过滤HasMany 关系,这可能吗?

上下文:一个有帖子的应用程序,每个帖子都有很多状态来保持历史。我想按每个帖子的最后状态过滤帖子。

帖子:

{
    public function statuses() 
    {
        return $this->hasMany(Status::class); // Only last one is important for querying
    }
}

然后,在一个范围内,我想做这样的事情:

public function scopeIsActive(Builder $builder)
{
    return $builder->whereHas('statuses', function(Builder $q) {
        // How to apply this ONLY to last created record???
        return $q->whereDate('activation', '<=', today());
    });
}

仅此而已!

编辑:(已解决查询)

经过一番挖掘,我用这个解决了我的问题:

public function scopeIsActive(Builder $builder)
{
    return $builder->whereHas('statuses', function (Builder $q) {
        return $q->whereDate('activation', '<=', today()) // applies to all
            ->where('statuses.id', function ($sub) { // applies to specific one
            return $sub->select('id')
                ->from('statuses')
                ->whereColumn('post_id', 'statuses.id')
                ->latest()
                ->limit(1);
        });
    });
}

而不是

public function others() 
{
    return $this->hasMany(Other::class); // Only last one is important for querying
}

你可以这样做:


public function other() 
{
    return $this->hasOne(Other::class)->latest();
}

然后

public function scopeCurrentActive(Builder $builder)
{
    return $builder->whereHas('other', function(Builder $q) {
        return $q->whereDate('activation', '<=', today());
    });
}

但是你不能自定义订单,如果你想自定义订单,你必须使用子查询:

return Model::orderByDesc(
    Other::select('arrived_at')
        ->whereColumn('model_id', 'model.id')
        ->orderBy('activation', 'desc')
        ->limit(1)
)->get();

如果想深入了解子查询,可以参考:

https://laravel-news.com/eloquent-subquery-enhancements

如果仅使用最后一条记录,您可能必须使用这样的 having 语句,但我不确定确切的语法 ^^


public function scopeIsActive(Builder $builder)
{
    return $builder->whereHas('statuses', function (Builder $q) {
        return $q->havingRaw(Other::select('arrived_at')
        ->whereColumn('model_id', 'model.id')
        ->orderBy('activation', 'desc')
        ->limit(1)->select('activation')->toSql(), '<=' , today());
    });
}

要按今天激活的项目进行过滤,请写:

public function scopeCurrentActive()
{
    return $this->whereHas('other', function($q) {
        return $q->whereDate('activation', '==', Carbon::now()->toDateString());
    });
}

不确定每个记录的最后一条记录

以下是获取所有与最新 post 具有相同状态的 post 的方法:

public function scopeIsActive(Builder $builder)
{
    $lastPostStatus = Post::select('status')
        ->orderBy('activation', 'desc')
        ->first()
        ->status;

    return $builder->where('status', $lastPostStatus);
}