当与模型链接的表为非自动增量时,Laravel 模型获取下一个增量 ID

Posted

技术标签:

【中文标题】当与模型链接的表为非自动增量时,Laravel 模型获取下一个增量 ID【英文标题】:Laravel Model get next increment ID when the Table linked with Model is Non-AutoIncrement 【发布时间】:2020-10-15 06:20:53 【问题描述】:

正如我在问题中提到的,我正在处理的当前 Laravel 6.0 项目有一些奇怪的数据库设置,其中模型(此处为 MainModel)mysql 表已设置为 AutoIncrementNULL。而且客户端根本不允许更改表格的定义。

我想在插入记录之前可靠地找到模型的下一个和上一个 ID(因为我无法从表中找到,因为 AutoIncrement 设置为 NULL),以便我可以输入相关记录(例如。通过将主模型的 ID 正确插入另一个表的引用 ID 字段,首先将推荐/常见问题或任何所见即所得内容字段的图像)插入另一个引用表。

目前我的主模型中有这个,但 next 方法不能可靠地一致地返回确切的递增 ID:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Te7aHoudini\LaravelTrix\Traits\HasTrixRichText;

class [MainModel] extends Model

    use HasTrixRichText;

    protected $guarded = [];
    public $timestamps = false;
    protected $primaryKey = 'id';
    protected $connection = '[connection1]';
    protected $table = '[main_table]';
    protected $fillable = ['id', '[titlefield]', '[wysiwyg_field]'];

    /**
     *  Setup model event hooks
     */
    public static function boot()
    
        parent::boot();
        self::creating(function ($model) 
            $model->id = $model->max('id') + 1;
        );
    

    /**
     * Get next available Faq Id
     */
    public function next()
    
        return ++$this->id;
    

感谢任何帮助...

【问题讨论】:

嗯...正在写一个答案,但很困惑为什么 next 有这个逻辑而不是重用引导方法的方法? 在插入之前没有可靠的方法来执行此操作,因为在识别和检索之间可能会发生竞争条件。 SELECT MAX(..) ... LOCK IN SHARE MODEINSERT 在同一事务中可能会取得一些成功。循环执行此操作以确保成功。向客户展示这一点,也许他们会看到原因并允许 AUTOINCREMENT 字段做他们想要做的事情。如果他们不这样做,请重新考虑是什么让作为客户有价值。 @mrhn 因为当我看到boot 方法时,$model 不是直接用在方法中而是在self::creating(function()) 方法中使用,你注意到了吗?所以我很困惑,我怎样才能在next 方法中获得$model-&gt;id ?我不认为$model 在扩展MainModel 中直接可用,是吗? 【参考方案1】:

据我了解,您对如何调用静态模型查询感到困惑。您可以通过使用静态自引用static 来实现相同的逻辑。

public static function next()

    return static::max('id') + 1;

这相当于。

MainModel::max('id');

使它成为避免 id 冲突的交易的奖励。这可以以有趣的方式锁定数据库,但会避免您拥有相同的 id,类似于此,非常简单的示例。

DB::transaction(function () 
    $model = MainModel::first();

    $id = $model->next();

    $newModel = MainModel::create(['id' => $id]);
);

【讨论】:

我想我知道你对什么感到困惑,但对于具体问题是什么还是有点困惑 :) else 评论,让我们从那里开始。 我想你可能刚刚解决了我的问题。这是我如何可靠地(在大多数情况下它需要工作,除非有 Mysql 服务器崩溃)获得模型中的下一个和上一个 ID 的唯一实际问题,该 ID 与奇怪的设置表链接,其中 AutoIncrementNULL ,您可以通过运行查询 SHOW TABLE STATUS LIKE '[main_table]'; 来验证 用事务示例更新了它,这将帮助您解决 id 冲突,似乎解决了?如果发生这种情况,我不会关心数据库是否关闭,您还有其他问题 :)【参考方案2】:

据我了解,为了获得下一个增量 id,您需要调用以下行。 模型::last()->first()

【讨论】:

以上是关于当与模型链接的表为非自动增量时,Laravel 模型获取下一个增量 ID的主要内容,如果未能解决你的问题,请参考以下文章

laravel 迁移在不是主要的时候使用自动增量

如何将自动增量设置为非主键?

dbwritetable 删除 mysql 中的自动增量字段

我应该如何为需要引用数据透视表的表配置 Laravel / OctoberCMS 模型?

如何在 Laravel 8 中获取与 json 有一个 hasMany 关系的表的所有模型?

创建具有自动增量的表