具有两个主键的 Laravel 模型更新 [重复]

Posted

技术标签:

【中文标题】具有两个主键的 Laravel 模型更新 [重复]【英文标题】:Laravel Model with Two Primary Keys update [duplicate] 【发布时间】:2016-07-19 19:47:13 【问题描述】:

我正在尝试更新具有两个主键的模型。

型号

namespace App;

use Illuminate\Database\Eloquent\Model;

class Inventory extends Model

    /**
     * The table associated with the model.
     */
    protected $table = 'inventories';

    /**
     * Indicates model primary keys.
     */
    protected $primaryKey = ['user_id', 'stock_id'];
...

迁移

Schema::create('inventories', function (Blueprint $table) 
    $table->integer('user_id')->unsigned();
    $table->integer('stock_id')->unsigned();
    $table->bigInteger('quantity');

    $table->primary(['user_id', 'stock_id']);

    $table->foreign('user_id')->references('id')->on('users')
        ->onUpdate('restrict')
        ->onDelete('cascade');
    $table->foreign('stock_id')->references('id')->on('stocks')
        ->onUpdate('restrict')
        ->onDelete('cascade');
);

这是应该更新 Inventory 模型的代码,但它没有。

$inventory = Inventory::where('user_id', $user->id)->where('stock_id', $order->stock->id)->first();
$inventory->quantity += $order->quantity;
$inventory->save();

我收到此错误:

Illegal offset type

我也尝试使用 updateOrCreate() 方法。它不起作用(我得到同样的错误)。

谁能告诉我们应该如何更新具有两个主键的模型?

【问题讨论】:

非法偏移类型,哪种类型?有行号吗?此查询中是否存在库存? 在 laravel/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php 第 2762 行出现 ErrorException。` /** * 获取 casts 数组。 * * @return array */ public function getCasts() if ($this->getIncrementing()) return array_merge([ $this->getKeyName() => 'int', // line 2762 ], $this- >铸件); 返回 $this->casts; ` 顺便说一下,这个库存存在。 粘贴完整的错误信息,以便我们可以在上下文中查看整个消息。 勾选这个github.com/laravel/framework/issues/5517 Laravel eloquent 不支持复合主键。 (旁注,您不能有两个主键。两个字段都是唯一主键的一部分) 完全错误pastebin.com/yaG0aZYM 【参考方案1】:

我遇到过几次这个问题。您需要覆盖一些属性:

protected $primaryKey = ['user_id', 'stock_id'];
public $incrementing = false;

和方法(credit):

/**
 * Set the keys for a save update query.
 *
 * @param  \Illuminate\Database\Eloquent\Builder  $query
 * @return \Illuminate\Database\Eloquent\Builder
 */
protected function setKeysForSaveQuery(Builder $query)

    $keys = $this->getKeyName();
    if(!is_array($keys))
        return parent::setKeysForSaveQuery($query);
    

    foreach($keys as $keyName)
        $query->where($keyName, '=', $this->getKeyForSaveQuery($keyName));
    

    return $query;


/**
 * Get the primary key value for a save query.
 *
 * @param mixed $keyName
 * @return mixed
 */
protected function getKeyForSaveQuery($keyName = null)

    if(is_null($keyName))
        $keyName = $this->getKeyName();
    

    if (isset($this->original[$keyName])) 
        return $this->original[$keyName];
    

    return $this->getAttribute($keyName);

记住这段代码需要引用 Eloquent Builder 类

use Illuminate\Database\Eloquent\Builder;

我建议将这些方法放在 HasCompositePrimaryKey Trait 中,这样您就可以在任何需要它的模型中使用 use 它。

【讨论】:

awsm。谢谢!它确实应该在基础框架中得到支持...... 我用这段代码做了一个特征,现在我只需要在我的模型上use CompositeKeyModelHelper;。谢谢! 将此添加到模型中,但它失败了。在调用此示例中列出的任何一个函数之前,似乎有东西在调用 Illuminate\Database\Eloquent\Model 中的 getKey(),导致抛出错误,因为它不期望属性数组。 好吧,你的权利,我使用不同的构建器!我更正了它,但它仍然无法正常工作:Declaration of App\Lookup\CountryStats::setKeysForSaveQuery(Illu‌​minate\Database\Eloq‌​uent\Builder $query) should be compatible with Illuminate\Database\Eloquent\Model::setKeysForSaveQuery(Illuminate\Database\Eloquent\Builder $query)。我不明白为什么,因为它与Model 中的方法具有相同的参数和可见性。我还注意到setKeysForSaveQueryModel 中没有输入参数。 如果使用此解决方案的人正在使用软删除。您还需要覆盖 runSoftDelete pastebin.com/d3ED089R

以上是关于具有两个主键的 Laravel 模型更新 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何通过多列理想地组合具有不同主键的两个表 HASH

具有新主键的重复记录 (VBA)

使用 Laravel Eloquent 使用复合键更新表

允许从重复记录中的一条记录到具有主键的表中

使用在多个列上具有主键的实体框架更新数据库

删除没有主键的重复项