Laravel模型递增ID?自增ID如何禁用?

32次阅读

禁用Laravel自增ID需在迁移中使用uuid(‘id’)->primary()并设置模型$incrementing = false和$keyType = ‘string’,以支持UUID主键。

Laravel模型递增ID?自增ID如何禁用?

Laravel模型默认是使用自增ID作为主键的,这是一种非常常见的做法,尤其是在单体应用中。但如果你有特定的需求,比如构建分布式系统、需要全局唯一标识符(UUID),或者要集成外部系统的数据,那么禁用这个自增特性,转而使用其他类型的主键,比如UUID,就是非常必要的。这个过程涉及数据库层面和Laravel模型层面的配置调整。

要禁用Laravel的自增ID,主要从两个方面入手:数据库迁移和Laravel模型。

  1. 数据库迁移文件(Migration) 在创建表的时候,不要使用$table-youjiankuohaophpcnid()或$table->increments(‘id’)。取而代之的是定义一个非自增的主键,例如一个UUID字段:

    Schema::create('your_table_name', function (Blueprint $table) {     $table->uuid('id')->primary(); // 定义一个UUID作为主键     // 或者,如果你想用其他非自增类型,比如一个字符串     // $table->string('id')->primary();     $table->string('name');     // ... 其他字段     $table->timestamps(); });

    这里,uuid(‘id’)->primary()明确告诉数据库,id字段是主键,类型是UUID,并且它不会自动递增。

  2. Laravel模型(Model) 在你的模型文件中,你需要告诉Laravel这个主键不是自增的。这通过设置$incrementing属性为false来实现。如果主键不是整数,你可能还需要设置$keyType属性。

    <?php  namespace appModels;  use IlluminateDatabaseEloquentFactoriesHasFactory; use IlluminateDatabaseEloquentModel;  class YourModel extends Model {     use HasFactory;      // 禁用自增ID     public $incrementing = false;      // 如果主键是UUID或其他字符串,需要指定键类型     protected $keyType = 'string';      // 默认主键名是'id',如果你的主键不是'id',还需要设置     // protected $primaryKey = 'your_custom_id_column';      // ... 其他模型属性和方法 }

    这样一来,Laravel在处理这个模型时就不会尝试去获取或设置一个自增的整数ID了。

为什么会考虑禁用Laravel的自增ID?

说实话,我个人觉得,在很多简单的CRUD应用里,Laravel默认的自增ID(通常是bigint unsigned auto_increment)简直是完美的。它简单、高效,数据库自动帮你管理,省心省力。但随着项目复杂度上升,尤其是当你开始接触微服务架构、分布式系统,或者需要数据同步、合并的场景时,自增ID的局限性就逐渐显现出来了。

我记得有一次,我们团队在开发一个多租户系统,每个租户都有自己的数据副本,但又需要一个全局唯一的标识符来追踪某些核心实体。如果还用自增ID,不同租户的数据合并起来就会出现ID冲突,简直是噩梦。这时候,使用UUID(Universally Unique Identifier)就成了自然而然的选择。UUID的优势在于它的全球唯一性,几乎可以保证在任何时间、任何地点生成的ID都不会重复。这对于分布式系统来说,简直是救命稻草,你不需要担心不同服务生成ID的碰撞问题。

此外,从安全角度考虑,自增ID也可能泄露一些信息。比如,一个URL里带着/users/1,/users/2,攻击者很容易就能猜测到用户总数,甚至尝试遍历ID来获取数据(当然,这需要配合其他安全漏洞)。而一个像users/a1b2c3d4-e5f6-7890-1234-567890abcdef这样的UUID,就很难被猜测和遍历,增加了系统的“黑箱”效应。当然,这不是说UUID就能替代所有安全措施,它只是一个辅助手段。

还有一种情况,就是你可能需要集成外部系统的数据,而这些外部系统已经有了自己的唯一标识符。如果强制使用Laravel的自增ID,你就需要在你的数据库里再维护一个外部ID字段,增加了数据冗余和同步的复杂性。直接把外部ID作为主键,能让数据模型更贴近业务实际。所以,虽然自增ID很方便,但它并非万能药,理解它的局限性,并在需要时切换到更适合的方案,这才是我们作为开发者应该深思熟虑的。

Laravel模型递增ID?自增ID如何禁用?

Spacely AI

为您的房间提供AI室内设计解决方案,寻找无限的创意

Laravel模型递增ID?自增ID如何禁用?32

查看详情 Laravel模型递增ID?自增ID如何禁用?

如何在Laravel模型中正确配置非自增主键?

上面在“解决方案”里已经提到了,主要是设置$incrementing = false;和protected $keyType = ‘string’;。但这里我想更深入地聊聊,为什么这两个配置如此重要,以及它们背后的逻辑。

当你将public $incrementing设置为false时,你实际上是在告诉Eloquent,这个模型的主键值不会由数据库自动生成并递增。这意味着,在保存新记录时,Eloquent不会尝试去数据库获取下一个自增值,也不会在INSERT语句中省略主键字段,期待数据库来填充。如果你不设置这个,而数据库字段又不是自增的,那么在尝试保存新模型时,你可能会遇到SQL错误,因为主键字段没有被赋值。

接着是protected $keyType = ‘string’;。这个配置是告诉Eloquent,你的主键不是传统的整数类型。Laravel内部在处理模型的主键时,有很多地方会默认假设主键是整数(例如,在一些类型转换、比较操作中)。如果你使用UUID(字符串类型)或者其他非整数类型作为主键,但没有设置$keyType = ‘string’,那么Eloquent可能会尝试将你的UUID字符串强制转换为整数,这显然会导致数据错误或意外行为。比如,它可能在某些场景下把你的UUID当成0来处理,那就麻烦了。

所以,这两个配置是相互配合的:$incrementing = false;告诉Eloquent主键不是自增的,而$keyType = ‘string’;则告诉Eloquent主键的类型是什么。它们共同确保了Eloquent能够正确地理解和处理你的非自增主键。如果你只设置了一个,很可能会遇到一些奇怪的、难以追踪的问题。我个人建议,只要你决定禁用自增ID,这两个配置就应该总是成对出现,除非你的非自增主键恰好还是整数类型(这种情况比较少见,但也不是没有)。

禁用自增ID后,如何管理主键的生成和赋值?

既然我们已经明确告诉Laravel和数据库,主键不再是自增的了,那么这个“唯一标识符”的生成和赋值工作,自然就落到了我们开发者身上。这其实给了我们更大的灵活性,但也意味着更多的责任。

最常见的做法是利用PHP的Str::uuid()方法(需要illuminate/support包,通常Laravel项目自带),或者直接在数据库层面使用UUID函数(如MySQL的UUID()函数,Post

以上就是Laravel模型递增ID?自增ID如何禁用?的详细内容,更多请关注laravel mysql php app 为什么 php laravel sql mysql 架构 分布式 String 标识符 字符串 整数类型 public protected 字符串类型 类型转换 table 数据库

laravel mysql php app 为什么 php laravel sql mysql 架构 分布式 String 标识符 字符串 整数类型 public protected 字符串类型 类型转换 table 数据库

text=ZqhQzanResources