将 Eloquent HasMany 关系转换为 HasOne?

Convert Eloquent HasMany relationship to a HasOne?

好的,我的模型 A 链接到许多模型 B,因此模型 A 与模型 BhasMany 关系,并且模型 B 与模型 A.

belongsTo 关系

但是,在所有这些 B 中,有一个特别的,例如价值更高的那个,我希望模型 A 与之建立专门的关系。

我知道我可以在模型 A 中创建第二个关系,重新使用旧关系并添加我想要的所有范围和条件,但由于我是从 hasMany,无论如何,它总是 return 一组结果。

有没有办法让它 return 成为一个结果而不是一个集合?我知道我可以添加一个 first(),但这涉及将这个新关系用作一个函数,即始终带有括号,如果可能的话,我仍然希望以 eloquent 的方式使用它。

可以吗?如果是,怎么做?

不是真的没有。您有 2 个模型映射表,其中一些属性如下

+-----+-----+
|  A  |  B  |
+-----+-----+
| id  | id  |
| ... | a_id|
|     | ... |
+-----+-----+

当您调用 hasMany 关系时,构建器会执行一个查询。像

SELECT * FROM `B` WHERE `B`.`a_id` = ?

如果为它创建不同的关系,则只会复制查询(如果同时加载这两个关系)。你可以做一个 accessor,或者只使用 first().

编辑访问代码:

# A model
public function getXAttribute()
{
    // Query only if necessary
    if(!this->relationLoaded('b')) $this->load('b');
    // Use Collection methods to filter
    return $this->b->firstWhere(...);
}

这个怎么样:

public function Bs()
{
    return $this->hasMany(B::class);
}

public function B()
{
    $builder = $this->Bs()->latest(); // Add your own conditions etc...

    $relation = new HasOne($builder->getQuery(), $this, 'a_id', 'id');

    return $relation; // or return $relation->withDefault();
}

更新:

Laravel 8.42 附带了一个新的一对多 关系。您可能想改用它:

public function B(): HasOne
{
    return $this->hasOne(B::class)->latestOfMany();
}