【问题标题】:Convert Eloquent HasMany relationship to a HasOne?将 Eloquent HasMany 关系转换为 HasOne?
【发布时间】:2020-01-08 10:41:48
【问题描述】:

好的,我有模型A 链接到许多模型B,所以模型AhasMany 关系到模型B 和模型BbelongsTo 关系到模型A.

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

我知道我可以在模型A 中创建第二个关系,重新使用旧的关系并添加我想要的所有范围和条件,但是由于我是从hasMany 建立这个新关系,它会无论如何,始终返回结果集合。

有没有办法让它返回单个结果而不是集合?我知道我可以添加一个first(),但这涉及使用这个新的关系作为一个函数,即总是带括号,如果可能的话,我想仍然以雄辩的方式使用它。

有可能做到吗?如果是,怎么做?

【问题讨论】:

    标签: eloquent relationship has-many has-one


    【解决方案1】:

    不是真的没有。您有 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(...);
    }
    

    【讨论】:

    • 感谢您的回答;所以你的意思是我需要在正确的条件下从AB 建立第二个hasOne 关系,以获得我想要的确切b
    • 不,只是像getXAttribute() { if(!this->relationLoaded('b'){ $this->load('b'); } returns $this->b->firstWhere(...); }这样的ab访问器
    【解决方案2】:

    这个怎么样:

    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 附带了一个新的 one-of-many 关系。您可能想改用它:

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

    【讨论】:

    • 谢谢@Mustafa,这真的很有趣,下次我会记住的;也许对于更复杂的用例,这会有所帮助。
    猜你喜欢
    • 2016-03-17
    • 2020-03-05
    • 2020-11-26
    • 1970-01-01
    • 1970-01-01
    • 2015-11-15
    • 2020-01-18
    • 1970-01-01
    • 2020-03-04
    相关资源
    最近更新 更多