【问题标题】:Force create an eloquent model through a relationship通过关系强制创建一个有说服力的模型
【发布时间】:2017-05-15 08:21:17
【问题描述】:

在一个使用 Laravel 5.3 和 Stripe 的小项目中,我试图通过 hasOne 关系在 User 上强制创建 Subscription

// User.php
public function subscription() {
    return $this->hasOne('App\Subscription');
}

public function subscribe($data) {
    return $this->subscription()->forceCreate(
        // $data contains some guarded fields;
        // create() will simply ignore them...
    );
}

但是,我明白了:

调用未定义的方法 Illuminate\Database\Query\Builder::forceCreate()

尽管forceCreate()valid Eloquent method

有什么想法可以模拟这种行为吗?或者我应该只是 save 一个 Subscription 手动分配每个字段?复杂之处在于某些字段应保留guarded,例如stripe_id.

编辑

我的快速解决方案:

// User.php @ subscribe($data)
return (new Subscription())
        ->forceFill([
            'user_id' => $this->id,
            // $data with sensitive guarded data
        ])
        ->save();

我相信还有更好的方法!

【问题讨论】:

    标签: php laravel eloquent relationship laravel-5.3


    【解决方案1】:

    $this->subscriptions() 的调用返回HasMany 类的实例,而不是Model

    createcreateMany 相反,HasOneOrMany 类中没有实现forceCreate()。因此,在这种情况下没有第一手的 API 可以使用。

    你看到了吗?当你调用$this->subscriptions()->create() 时,你调用的是HasMany 实例上的create 方法,而不是Model 实例。 Model 类有一个 forceCreate 方法这一事实与此无关。

    您可以使用getRelated() 方法获取相关模型,然后调用forceCreate()unguarded()

    public function subscribe($data) {
        return $this->subscription()
                    ->getRelated()
                    ->forceCreate($data);
    }
    

    但是这种方法有一个严重的缺点;它没有设置关系,因为我们正在从关系中提取模型。要解决它,您可能会说:

    public function subscribe($data)
    {
        // $data['user_id'] = $this->id;
        // Or more generally:  
        $data[$this->courses()->getPlainForeignKey()] = $this->courses()->getParentKey();
    
        return $this->courses()
                    ->getRelated()
                    ->forceCreate($data);
    }
    

    呃,看起来太老套了,不是我的做法。我更喜欢不保护底层模型,调用create 然后重新保护它。大致如下:

    public function subscribe($data)
    {
        $this->courses()->getRelated()->unguard();
    
        $created = $this->courses()->create($data);
    
        $this->courses()->getRelated()->reguard();
    
        return $created;
    }
    

    这样,您不必手动设置外键。

    laravel/internals 相关讨论:
    [PROPOSAL] Force create model through a relationship

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-24
      • 2014-04-02
      • 1970-01-01
      • 1970-01-01
      • 2020-03-30
      相关资源
      最近更新 更多